1 (edited by joshuA 2021-10-22 23:12:18)

Topic: [SOLVED] Filter a Datetime field by Month and Year only

Greetings,
.
I searched and found similar posts to this, but they are using older versions...  I'm trying to filter records containing a DateTime field by the Month and Year only.  Showing all days and times within the selected month and year.
.
I have gotten this to work using two separate Date and Time fields, but it doesn't seem to work the same with a single DateTime field unless I use the >= Filter.  But, I would rather it be for a specific month and year instead.
.
In the other test project using a Date and Time field, the time would always be 00:00:00 in the date field and the date would always be 1899-12 in the time field.  So, I thought that it's probably better to use a single field instead.
.
I've attached an experiment project.  Is this possible, what am I doing wrong?

Post's attachments

Attachment icon datetime-filter.zip 326.51 kb, 242 downloads since 2021-10-10 

"Energy and persistence conquer all things."

Re: [SOLVED] Filter a Datetime field by Month and Year only

This might help you.

Post's attachments

Attachment icon datetime-filter_2.zip 550.33 kb, 283 downloads since 2021-10-11 

brian

3 (edited by sparrow 2021-10-11 12:22:41)

Re: [SOLVED] Filter a Datetime field by Month and Year only

You can create event frmMain_dtpFilter_OnChange
and write to script

procedure frmMain_dtpFilter_OnChange (Sender: TObject);
begin
  frmMain.TableGrid1.dbFilter := 'event.eDate >= '+frmMain.dtpFilter.sqlDate+' AND event.eDate < strftime(''%Y-%m'','+frmMain.dtpFilter.sqlDate+',''+1 month'')';
  frmMain.TableGrid1.dbUpdate;
end;

Remove the name btnSearch from dtpFilter(Increm.Search) and the search button itself.


OR


you can do it via SQL query on the button.
Write your query and process one DateTimePicker.

SELECT event.name, event.eDate, event.id
FROM event
WHERE event.eDate >= {dtpFilter} 
AND event.eDate < strftime('%Y-%m',{dtpFilter},'+1 month')

The disadvantage of this approach is writing your own query and processing the table when changing (event OnChange)

Re: [SOLVED] Filter a Datetime field by Month and Year only

Thank you brian, and sparrow.
.
This turns out to be more involved than I expected (with scripts).  But I am glad that it's not as simple as changing properties in the controls, because I feel like I tried many different combinations with all of them at some point.
.
I have learned something from both.
.
But again, I appreciate you both for taking time to answer.

"Energy and persistence conquer all things."

5 (edited by joshuA 2021-10-13 02:00:06)

Re: [SOLVED] Filter a Datetime field by Month and Year only

So progressing a little further... At first, I liked sparrow's simple two lines, but I have implemented brian's solution because it was easier to do reports without using Report (SQL).
.
I have a few other questions now for anyone:
.
1) The tableGrid shows the time formatted (in 12-hour format) which is how I would like to extract it.  I know this doesn't apply, but the C++ reference to strftime has a %I.  That's what I'm looking for here.
.
I have three different sites I reference for the SQLite strftime function, but they only show %H for the 24-hour portion.  Also, most all the related posts here that I've skimmed mainly deal with the date portion.
.
So, my cfTime is using: strftime('%H:%M',event.eDateTime) for now.
.
I'm working on a conversion.  So, I created a cfHour to convert it, but I'm wondering if there is a better way to do this?  I need to report the time also.
.
2) I have a cfMonthName field primarily for the reports.  Because I can never get FastReport to DisplayFormat to work.  I tried this on the eDateTime field (the red date on the report):
.
Report
  DisplayFormat
    FormatStr: mmmm
    Kind: fkDateTime
.
But it only shows the full date.  I'm guessing this is not an option?  So, the cfMonthName is necessary in this case.

Post's attachments

Attachment icon datetime-filter-3.zip 330.01 kb, 248 downloads since 2021-10-13 

"Energy and persistence conquer all things."

6 (edited by brian.zaballa 2021-10-13 07:03:56)

Re: [SOLVED] Filter a Datetime field by Month and Year only

I rarely use calculated fields on the applications I am working on. I rather use trigger or save-it-in-database. This might be a workaround on what you are looking for.


I also updated the filter date, since entering a record that will fall in the last day of the month will not be displayed on the search.
I just added 0.99999 (less than a millisecond/second for a day)


Try changing this line too

frmDetail.a_ampm.Text := FormatDateTime('AM/PM',frmDetail.dtpDate.DateTime);

to

frmDetail.a_ampm.Text := FormatDateTime('hh:nn AM/PM',frmDetail.dtpDate.DateTime);

It might be the one you are looking for. I just go with what your calculated fields do.


PS: I didn't change the report. just the saving part. You might want to just update it.

Post's attachments

Attachment icon datetime-filter-3.1.zip 554.57 kb, 224 downloads since 2021-10-13 

brian

7 (edited by sparrow 2021-10-13 14:03:37)

Re: [SOLVED] Filter a Datetime field by Month and Year only

Hi,

in the program you can use the advice brian.zaballa but for REPORT :


1. red field "(the red date on the report)" in REPORT write new text

[StrToDateTime(<Report."event.eDateTime">)]

2. in format tab select Date\Time and "format string" type mmmm (or what do yo want... for example hh:mm am/pm wink )
the same as
  DisplayFormat
    FormatStr: mmmm
    Kind: fkDateTime


OR


1. red field "(the red date on the report)" in REPORT write new text (month or time with am/pm)

[FormatDateTime('mmmm',StrToDateTime(<Report."event.eDateTime">))] 
or
[FormatDateTime('hh:nn:ss am/pm',StrToDateTime(<Report."event.eDateTime">))]
or
[StrToDateTime(<Report."event.eDateTime">) #dmmmm]
or
[StrToDateTime(<Report."event.eDateTime">) #dhh:mm am/pm]

2. in format tab select Text (no formatting).
the same as
  DisplayFormat
    FormatStr:
    Kind: fkText


Thats all

The date and time is displayed in the table and in the program depending on the regional settings in WINDOWS. But if you really need it, you can create a calculated field with something like this(adapted from the internet ). And output it to a table.

CASE WHEN strftime('%H', eDateTime) % 12 = 0 
        THEN 12 
        ELSE strftime('%H', eDateTime) % 12 END 
        || ':' || strftime('%M', eDateTime)
    || ' ' ||
    CASE WHEN
        strftime('%H', eDateTime)-0 >= 12 THEN 'PM'
        ELSE 'AM' END 

8 (edited by joshuA 2021-10-14 00:59:01)

Re: [SOLVED] Filter a Datetime field by Month and Year only

Thanks again to both of you for contributing your hints and techniques here!
.
It's a little too late to mention this now, but for this project it wasn't necessary for the AM/PM part.  But you both have thoroughly covered that in detail, and I will use it for the future- I'm sure.


brian,
.

I rarely use calculated fields on the applications I am working on. I rather use trigger or save-it-in-database.

.
I am curious about this...  Will you elaborate on cases when you would and would not use calculated fields?  (just in general)
.
Also in your example, you saved-it-in-database, but I'm not sure that I am familiar with what you meant by "use trigger".  Will you describe what this is too, please?
.
And thanks for pointing out that 0.99999 detail, because I started using this technique in some of my other projects now wink
.
No worries about the reporting, I will adjust it too.  Who prints anything these days, right? lol


sparrow,
.
Your code snippet for the red field text in FastReport is precisely what I was looking for, Thank you!  But this also leads me to believe (and answers my very last question about the DisplayFormat property in FastReport) that it doesn't work. Perhaps this is the proper way to accomplish this with MVD and its included version of FastReport.
.
Going back to your other suggestion:
.

2. in format tab select Date\Time and "format string" type mmmm (or what do yo want... for example hh:mm am/pm   )
the same as
  DisplayFormat
    FormatStr: mmmm
    Kind: fkDateTime

.
[edit]
Excuse me, I follow what you were saying now... you have to make that call in the report prior to changing those properties AND THEN it will display that format...
[/edit]
.
Your last CASE WHEN example is much cleaner than the one I was using.  The modulus operator didn’t come to mind, nor did searching for a generic solution to that.  I get tunnel vision sometimes, so I just resorted to using that similar structure for the SQL line to convert the month numbers into words.


Many many thanks guys, I’m still learning the MVD ways, and this has helped a bunch!

"Energy and persistence conquer all things."

Re: [SOLVED] Filter a Datetime field by Month and Year only

Sometimes, when working with bunch of record/row in my database, complex calculated field make my application slow, even hang sometimes especially for the users with a low-spec computers. But then I use it(calculated) in some cases.


Trigger is a piece of code inside your database. you have to code it manually,
I'm putting some of the business logic inside the database using trigger., think of it as an auto-query triggered before/after insert, update and delete. with values NEW.[field] and OLD.[filed] which you can use to update/insert/delete other record from other table of the database.


You can search for "trigger in sqlite" for that.


Just be careful for updating fields on a table using MVD will delete the trigger or sometimes prevent updating it. My way of doing trigger is to have a file and save all triggers there. Here's a sample of my trigger to give you an idea

DROP TRIGGER IF EXISTS "main"."debit_post";
CREATE TRIGGER "main"."debit_post"
AFTER UPDATE OF "dbt_is_posted"
ON "debit"
WHEN ((OLD.dbt_is_posted=0) AND (NEW.dbt_is_posted=1))
BEGIN        
    DELETE FROM commitment_payment WHERE id_commitment in (SELECT DISTINCT(id_commitment) FROM debit_commitment WHERE id_debit=NEW.id);

    INSERT INTO commitment_payment(
        id_commitment, id_account, id_fms_budget, amt, dtime, id_debit    
    )
    SELECT 
        debit_commitment.id_commitment,
        fms_budget.id_account,
        fms_budget.id,
        CASE WHEN (debit_commitment.fms IS NOT NULL ) THEN 
            SUM(debit_commitment.dbtc_amt)
        ELSE 
            debit.dbt_amt
        END
        as amt,
        debit.dbt_dtime AS dtime,
        debit.id as dvid
    FROM debit_commitment
    LEFT JOIN debit ON debit.id=debit_commitment.id_debit
    LEFT JOIN fms_budget ON fms_budget.id = 
        CASE
            WHEN (debit_commitment.id_fms_budget IS NULL ) THEN debit_commitment.fms
            ELSE debit_commitment.id_fms_budget
        END
    WHERE id_debit=NEW.id
    GROUP BY CASE
        WHEN (debit_commitment.id_fms_budget IS NULL ) THEN debit_commitment.fms
        ELSE debit_commitment.id_fms_budget
    END, fms_budget.id_account;
    UPDATE bdcm SET dbt_is_posted = 1 WHERE id_debit = NEW.id;
END;

Then before updating field using MVD, I am deleting all triggers created then re-run it(copy-paste). I'm using Database manager(Navicat) when creating and updating triggers. Save so much time. There are free software too like DBeaver, DB Browser, etc. I think some of then can create trigger too with just a few clicks. But knowing how to construct it manually is a great advantage.


You can put aside trigger for now and try to study it first.

brian

10 (edited by sparrow 2021-10-14 07:34:47)

Re: [SOLVED] Filter a Datetime field by Month and Year only

Check out an example. The REPORT uses only the eDateTime field. Shows month and time as am / pm.
yellow and green fields show different methods
in the table of form1 the 'time am / pm' field is displayed

Post's attachments

Attachment icon datetime-filter-32.zip 338.8 kb, 258 downloads since 2021-10-14 

Re: [SOLVED] Filter a Datetime field by Month and Year only

It is possible in this way for a table column. Then there is no need for a calculated field

TNxNumberColumn(Form1.TableGrid1.Columns[i]).FormatMask := 'hh:nn am/pm';

Re: [SOLVED] Filter a Datetime field by Month and Year only

brian,
.
Thank you for the explanations.  I will try to learn a bit more about triggers now, because it sounds like they would be useful in the next step of this project.  This is where my knowledge with SQL ends.  I have heard about triggers, but I've never used them before... so the journey beings.
.
Thanks also for the tip about saving them outside of MVD.  I'm sure this will be very useful once I learn more about them.
.
As far as the calculated fields, I'm sure it depends on the situation (as always).  But I was just curious if you had some determining factors that made you go one way or the other on when to use them.
.
sparrow,
.
I can't explain how helpful it is for me to finally get this formatting issue resolved in FastReport- I was beginning to think it wasn't possible.  I appreciate the comparison between the two ways of doing this in your example too.  I'm beginning to understand this a bit more now, and I really appreciate both of your contributions!
.
Regarding your last post, I don't follow where that would go.  The TNxNumberColumn makes me think of a report...  But then again, the complete line seems like the syntax inside a script procedure call... I can't decide for sure tho.
.
Thanks once again guys!

"Energy and persistence conquer all things."

Re: [SOLVED] Filter a Datetime field by Month and Year only

TNxNumberColumn will change the format displayed on the grid, you can put it in the OnChange Event of the grid.


To give you an idea, I've created and using a procedure(not with date thou but the idea is the same) in my projects that Format display of a field(a calculated one) into a money format

{
    Format Column in a Grid
    Called in onChange Event of a Grid

  FormatMoneyGrid(main.grdOR, 1);
}
procedure FormatMoneyGrid(TblGrid: TdbStringGridEx; column: integer; formatFooter:Boolean=True);
begin
    TNxNumberColumn(TblGrid.columns[column]).FormatMask := '#,##0.00';
    TblGrid.columns[column].Alignment := taRightJustify;
    if formatFooter then
        TblGrid.Columns[column].Footer.Caption := FormatFloat('#,###,##0.00', TblGrid.Columns[column].Footer.FormulaValue);
end;

Then I call it on Onchange event

procedure frmObligationToPay_grdOBWB_OnChange (Sender: TObject);
begin
    FormatMoneyGrid(frmObligationToPay.grdOBWB, 4, True);
end;

I'm using it when MVD didn't automatically formatting it on the grid. You might want to use it in the future when you are having trouble displaying calculated currency on the grid.:)

brian

14 (edited by joshuA 2021-10-16 21:47:22)

Re: [SOLVED] Filter a Datetime field by Month and Year only

Hi brian, thanks for that example too.
.
I know this is spinning off into another direction now (from the original post).  I wasn't sure whether to create a new topic, so I'm continuing here for now.  It's related to date and time, and specifically towards your last example...
.
So after getting further into my project, I decided that it might be better to separate the two fields.  eDate and eTime instead of using a single eDateTime field like I originally decided to do.  I'll get into that a bit later.
.
I was using your column format example above, but I'm getting an error.  Instead of formatting money though, I'm formatting time.  I don't see why that would be an issue though- maybe it is?
.
The frmMain_OnShow event includes:

TNxNumberColumn(frmMain.TableGrid1.Columns[2]).FormatMask := 'H:mm';

.
And that works fine, until the grid changes (loosing the format), but when I place that line inside the frmMain_TableGrid1_OnChange event it halts the program and says:
.
List index out of bounds (2)
.
There are only 3 columns: Name [0], Date [1] and Time [2]
.
When I change it to Columns[1] it's applying it to the date column (which is expected).  I haven't tested the code in your example, but I'm sure it works.  So the only other thing I can think of is that you're calling a custom procedure, but it's doing the same thing.  Might be in a different order though...  Any thoughts?
.
[edit]
Just because I was curious I tried two other ideas:
.
1. using TNxTimeColumn instead of TNxNumberColumn
2. calling from a custom procedure like in your example
.
Still the same error complaining about an invalid column index
[/edit]

"Energy and persistence conquer all things."

15 (edited by brian.zaballa 2021-10-17 03:26:46)

Re: [SOLVED] Filter a Datetime field by Month and Year only

Check your grid Settings, make sure you are not loading any data from it if you are using search button to load your data, vice versa. It's either you are missing a filed on Grid Settings or in the Search Button. Check it out and go back with OnChange of the grid.

Other possible cause, if you are sure your grid has no problem in field count, then check other grid, on your appliication, sometimes, copy-paste of grid will cause you error such as this when you didn't remove/change that OnChange event of the copied grid.

brian

16 (edited by derek 2021-10-17 18:36:51)

Re: [SOLVED] Filter a Datetime field by Month and Year only

Hi Joshua, Brian, Sparrow,
I've been away and now playing 'catch-up' and have just seen your post.
I'm not sure if you've now moved on, but with regard to your original issue (filtering by month), I usually do it like this (see attached).
I also like to have the 'show checkbox' visible otherwise once you start filtering, there's no easy way of getting back to 'all' data.
As always with MVD, there are different ways to approach a problem.
Derek.

Post's attachments

Attachment icon month filter.zip 337.97 kb, 251 downloads since 2021-10-17 

17 (edited by joshuA 2021-10-18 13:05:57)

Re: [SOLVED] Filter a Datetime field by Month and Year only

Hi folks,
.
Welcome back derek, and thanks for chiming in on this.  No, I haven't moved on as I'm still weighing out the different options and how to approach it.


brian
Thanks for your last suggestions.  I was able to get it working in a different project, so I'm pretty sure it's a timing issue with when the format is being applied in the project with the error.
.
I do have another question now though... but let me add an extra detail to this:
.
There will always be a date, but the time is optional.  I noticed in the default tableGrid formatting of the DateTime field that when the time is midnight 00:00:00, it doesn't even display the time (and I prefer this).  However, when that grid format is applied, the time 00:00 is always displayed.  Is there a way to ignore the time when it's midnight like in the default?
.
In my attached example, I am using a button instead of the OnChange event to demonstrate my question above.


derek
I have a few questions about your project, if you will.
.
1. Also in my attached example, I used your approach without the event.cfmonth but instead event.eDate.  Do you see where this could cause a problem?  Is the cfmonth necessary?
.
2. In your example, you use copy(frmmain.dtpfilter.sqldate,2,7).  I was trying to figure out why you start with 2.  I tested 0 and 1, and in both cases it included the first double quote ".  Are 0 and 1 returning the same thing in this case?  Would you explain this further, please?
.
Also thanks for the suggestion for leaving the checkbox on the filter date.  I hadn't thought about that.


general questions
1.
It's not necessary to deal with seconds or mseconds with the time field.  On the frmDetail when I use format HH:mm, it indeed hides the seconds and the AM/PM, but it's still recording the seconds and possibly the mseconds.  I need those to always be 00 in any case.  That way- if there is a way to do the formatting described above, the time will be hidden in the tableGrid.
.
2.
Because the time is optional, on the frmDetail the dtpTime is linked to the dtpDate, so when the Time is unchecked the date is also not saved.  I have some ideas on how keep the time excluded (maybe by using other hidden controls and scripts).  Is there a better way of doing this?
.
This is the issue I was having in my last post where I was talking about using two separate fields again.  I don't particularly like this idea.  So I'm still experimenting for now.


[edit] forgot to add the project tongue [/edit]

Post's attachments

Attachment icon datetime-filter-40.zip 327.68 kb, 219 downloads since 2021-10-18 

"Energy and persistence conquer all things."

18 (edited by derek 2021-10-18 23:53:27)

Re: [SOLVED] Filter a Datetime field by Month and Year only

Hi Joshua,
To answer a couple of specific questions:
1.  No, cfmonth isn't strictly necessary - I only do it that way in case I need to carry it across to FastReport to break on change of month.
2.  Yes, when you use 'copy' to chop up and reformat dates, it needs to start at 2 to remove the quote.
You also mentioned about 'time' being optional - maybe you could preset the time to 00:00 and then in the tablegrid, test for 00:00 and then blank them out.  The only issue would be when there is a genuine time of midnight that you need to record - not sure if that would ever happen. 
If it does, I'm sure there are ways around it - but for now, I was trying to keep things simple.
Derek.

Post's attachments

Attachment icon datetime-filter-40a.zip 339.29 kb, 243 downloads since 2021-10-19 

Re: [SOLVED] Filter a Datetime field by Month and Year only

Hi derek,
.
I appreciate your response (and the extra explaination), as always!
.
I didn't mean to take away your cfmonth, I was more curious if it could be done (and if there were any differences).  I would probably need to carry it across to FastReport, so thanks for using that technique.
.
Yes- at first, I was presetting the time.  Then I got the idea to show and use the checkbox for the time field.  That was working good until I wanted to remove the display of seconds and AM/PM.  So I noticed after reformatting the tableGrid it started showing the 00:00.  I do like the way the default simply doesn't show if it's 00:00, but I'm guessing that's also a result of whether or not the checkbox is checked.  Haven't tested that.
.
For this project, there is only ever a 12-14 hour window, and so a time of 00:00 falls outside of it.  So it worked out that the default tableGrid was hiding that hour.  My apologies for not mentioning that detail, and thanks for considering it.
.
So testing values in the tablegrid is new to me, so I wasn't even sure how to make that happen.  I might have more questions once I look it over more closely, but for now- Thank you.

"Energy and persistence conquer all things."

20 (edited by joshuA 2021-10-22 11:41:29)

Re: [SOLVED] Filter a Datetime field by Month and Year only

Okay, so I made some minor changes to get the results I had in mind:
.
So since the date is always required, I hide the checkbox for that field.  I created a "dummy" hidden time field to always store the time.  And I wanted to make use of the checkbox (for the user interface) on the visible time field because it is optional.
.
This is what I came up with, and it seems to be working okay.  But I would appreciate any feedback from anyone that will have a look at it.


Again derek, I appreciate that example with the tableGrid conditions and testing.  Very helpful for me.  I haven't done any of that yet.


I have some arbitrary questions (for anyone that has posted in this thread) about some of your settings (in the IDE I guess).  When some of you offer solutions:
.
1. I notice the tabstops or spacing is set to two.  The default in MVD is like four, so I'm just curious if you folks use a different editor for the scripts?  Because I see no way to change this in MVD.  (Unless you don't use the tab key lol )
.
2. Also (particularly with derek) the Grid size seems to be different.  Mine is set to eight which is the installation default.  I notice because without manually changing position values, my controls don't ever line up with the ones from your projects.
.
These are kinda random questions, but I have always been curious.

Post's attachments

Attachment icon datetime-filter-40b.zip 329.38 kb, 229 downloads since 2021-10-20 

"Energy and persistence conquer all things."

21 (edited by sparrow 2021-10-20 19:29:42)

Re: [SOLVED] Filter a Datetime field by Month and Year only

Hi JoshuA, Derek
The simple line strftime ('% Y-% m', edate) works fine in cfmonth.
It is possible and even easier For TextBox to specify FieldName - edate (write by hand).
In the example in the left and right tables, both solutions.

Post's attachments

Attachment icon 7792_datetime-filter-40b_joshuA_sp.zip 338.6 kb, 300 downloads since 2021-10-20 

22 (edited by derek 2021-10-20 20:26:27)

Re: [SOLVED] Filter a Datetime field by Month and Year only

Hi Joshua, Sparrow,
Had a quick look and the combination of no checkbox (for the date) and optional checkbox (for the time) seems to cover all the bases and is intuitive - don't think you'll get it much better than you already have.
And on a couple of specific points:
1.  Sparrow's way of setting cfmonth - strftime('%Y-%m') - is much nicer - wish I'd thought to do it that way.
2.  You're right - I don't use the 'tab' key!  I guess it's a throwback to when editors were VERY basic and didn't have 'tabs' and so I've always just indented by two spaces;  put it down to force of habit.
3.  I run a computer class for older people whose eyesight often isn't great so it helps to play around with the default grid sizes, fonts, spacing, default label sizes etc.
Derek.

Re: [SOLVED] Filter a Datetime field by Month and Year only

Great!
.
Thanks to each of you for being patient and making suggestions.  I'm still learning how to create a decent database.  This portion of my project is complete, and it's working good now.
.
Yeah derek, I know those things are purely preference and sometimes habit.  I had been wondering all this time, so thanks for sharing.  I have experimented with the grid size some, and I do like the grid size on a smaller number than the default now.
.
Many many thanks!

"Energy and persistence conquer all things."