Recent

Author Topic: SQLite3 Date Problem  (Read 4954 times)

Handoko

  • Hero Member
  • *****
  • Posts: 5386
  • My goal: build my own game engine using Lazarus
Re: SQLite3 Date Problem
« Reply #15 on: November 18, 2024, 08:13:04 pm »
Yes, we need an example. Bug can hide in anywhere in the code. Preferable a downloadable compile-able source code with sample data.

paweld

  • Hero Member
  • *****
  • Posts: 1278
Re: SQLite3 Date Problem
« Reply #16 on: November 18, 2024, 08:45:47 pm »
Quote from: pat03uk
Iā€™m saving the date as a string as 2022-12-05 (see first post)
in that case, use the OnGetText event - modified sample in attachment
Best regards / Pozdrawiam
paweld

Sieben

  • Sr. Member
  • ****
  • Posts: 372
Re: SQLite3 Date Problem
« Reply #17 on: November 18, 2024, 10:43:56 pm »
That's what i would also suggest, given the fact that ISO8601 text is indeed the recommended date format in SQLite. And by converting the ISO string first into a TDateTime and then back to a string you have all the 'freedom of formatting' you'd have formatting an incoming TDateTime - which can be as straightforward as this:

Code: Pascal  [Select][+][-]
  1. const
  2.   cISODate = 'yyyy-mm-dd';  // might also be local to the procedure
  3.  
  4. procedure TdmMain.qHauptDatumGetText(Sender: TField; var aText: string; DisplayText: Boolean);
  5. begin
  6.   if DisplayText and not Sender.IsNull then
  7.   begin
  8.     aText := Sender.AsString;
  9.     aText := DateToStr(StrToDate(aText,cISODate,cISODate[5]));
  10.   end;
  11. end;

DateToStr of course being a function using DefaultFormatSettings. But you can use a variety of other functions and overloads to customize your formatting.
Lazarus 2.2.0, FPC 3.2.2, .deb install on Ubuntu Xenial 32 / Gtk2 / Unity7

rvk

  • Hero Member
  • *****
  • Posts: 6643
Re: SQLite3 Date Problem
« Reply #18 on: November 19, 2024, 09:36:58 am »
Using GetText is a poor solution for a problem that does not exist.

We don't even know anything about the table structure. How is that date field defined?
What if you want to use that field to do some data calculations (like number of days since) inside a SELECT statement.

For me the code below works fine in FPC so there is no problem with strftime, even if it deals with a TEXT defined field.

But it might be better to just let SQLite3 determine the affinity and use DATE (in which case it will pick NUMERIC as underlying field).
https://www.sqlite.org/datatype3.html

Code: Pascal  [Select][+][-]
  1. program test;
  2.  
  3. {$MODE OBJFPC}{$H+}
  4.  
  5. uses
  6.   Classes, SysUtils, dateutils, DB, sqldb, sqlite3conn;
  7.  
  8. var
  9.   Conn: TSQLite3Connection;
  10.   Trans: TSQLTransaction;
  11.   Query: TSQLQuery;
  12.   n: Integer;
  13. begin
  14.   DeleteFile('test.db');
  15.   Conn := TSQLite3Connection.Create(nil);
  16.   Conn.DatabaseName := 'test.db';
  17.   try
  18.  
  19.     Trans := TSQLTransaction.Create(Conn);
  20.     Trans.Database := Conn;
  21.     Query := TSQLQuery.Create(Conn);
  22.     Query.Database := Conn;
  23.     Query.Transaction := Trans;
  24.  
  25.     Conn.ExecuteDirect('CREATE TABLE data (id INTEGER, xdate text);');
  26.     // but xdate DATE might be better here
  27.  
  28.     Query.SQL.Text := 'INSERT INTO data (id, xdate) values (:id, :xdate)';
  29.     for n := 1 to 10 do
  30.     begin
  31.       Query.Params.ParamByName('id').AsInteger := n;
  32.       Query.Params.ParamByName('xdate').AsDate := Date;
  33.       // Query.Params.ParamByName('xdate').AsString := '2023-12-05'; // this works too
  34.       Query.ExecSQL;
  35.     end;
  36.     Trans.Commit;
  37.  
  38.     Query.SQL.Text := 'SELECT id, strftime(''%d/%m/%Y'', xDate) as xdate FROM DATA';
  39.     Query.Open;
  40.     while not Query.EOF do
  41.     begin
  42.       writeln(format('id = %d  xdate = %s', [Query.FieldByName('id').AsInteger, Query.FieldByName('xdate').AsString]));
  43.       Query.Next;
  44.     end;
  45.  
  46.   finally
  47.     Conn.Free;
  48.   end;
  49.  
  50.   readln;
  51.  
  52. end.

Quote
id = 1  xdate = 19/11/2024
id = 2  xdate = 19/11/2024
id = 3  xdate = 19/11/2024
id = 4  xdate = 19/11/2024
id = 5  xdate = 19/11/2024
id = 6  xdate = 19/11/2024
id = 7  xdate = 19/11/2024
id = 8  xdate = 19/11/2024
id = 9  xdate = 19/11/2024
id = 10  xdate = 19/11/2024

The problem is probably the predefined fields in the IDE object inspector (which causes the blank fields).
« Last Edit: November 19, 2024, 09:39:37 am by rvk »

Thaddy

  • Hero Member
  • *****
  • Posts: 16420
  • Censorship about opinions does not belong here.
Re: SQLite3 Date Problem
« Reply #19 on: November 19, 2024, 10:59:32 am »
Correct, with one extra remark: dates in a database should always be stored as UTC time so the date becomes independent of location and time zone.
There is nothing wrong with being blunt. At a minimum it is also honest.

Sieben

  • Sr. Member
  • ****
  • Posts: 372
Re: SQLite3 Date Problem
« Reply #20 on: November 19, 2024, 12:36:07 pm »
Quote
We don't even know anything about the table structure. How is that date field defined?

We have some clues from TS' first post here:

Quote
I enter the date eg 05/12/2022 as the string 2022-12-05 into Text Field

which is of course a ISO8601 text representation of a date, stored to a SQLite TEXT data type field.

Quote
What if you want to use that field to do some data calculations (like number of days since) inside a SELECT statement.

SQLite is perfectly happy to perform calculations on an ISO8601 text representation of date and time values:

https://www.sqlite.org/lang_datefunc.html

And DateUtils provides functions that take UTC into consideration:

Code: Pascal  [Select][+][-]
  1. function DateToISO8601(const ADate: TDateTime; AInputIsUTC: Boolean = True): string;
  2. Function ISO8601ToDate(const DateString: string; ReturnUTC : Boolean = True): TDateTime;
  3. Function ISO8601ToDateDef(const DateString: string; ReturnUTC : Boolean; aDefault : TDateTime ): TDateTime; deprecated;
  4. Function ISO8601ToDateDef(const DateString: string; aDefault : TDateTime; ReturnUTC : Boolean = True ): TDateTime;
  5. Function TryISO8601ToDate(const DateString: string; out ADateTime: TDateTime; ReturnUTC : Boolean = True) : Boolean;

I would even go so far as suggesting that ISO8601 will over time become a if not the standard of database date and time storage.
Lazarus 2.2.0, FPC 3.2.2, .deb install on Ubuntu Xenial 32 / Gtk2 / Unity7

pat03uk

  • New Member
  • *
  • Posts: 20
Re: SQLite3 Date Problem
« Reply #21 on: November 19, 2024, 12:47:04 pm »
I have a minimal project that shows the problem

I need to have the dbgrid show the date as dd/mm/yyyy

The zipped file is 4.9MB which appears to be too big to attach

Any way around this?
« Last Edit: November 19, 2024, 12:50:26 pm by pat03uk »

rvk

  • Hero Member
  • *****
  • Posts: 6643
Re: SQLite3 Date Problem
« Reply #22 on: November 19, 2024, 01:01:55 pm »
The zipped file is 4.9MB which appears to be too big to attach

Any way around this?
Remove any .exe and .res from the zip.
Only .pas .pp .rc .lfm .lpi .lpr .lps files remain.
Should be very small then.

TRon

  • Hero Member
  • *****
  • Posts: 3822
Re: SQLite3 Date Problem
« Reply #23 on: November 19, 2024, 01:21:17 pm »
Or Lazarus IDE, project, publish project. Tick the compress checkbox and set the directory. Then upload the created archive.
I do not have to remember anything anymore thanks to total-recall.

rvk

  • Hero Member
  • *****
  • Posts: 6643
Re: SQLite3 Date Problem
« Reply #24 on: November 19, 2024, 01:44:38 pm »
Or Lazarus IDE, project, publish project. Tick the compress checkbox and set the directory. Then upload the created archive.
That will also include the .res which sometimes can be large.
Never understood why it was standard included there.
.res should be automatically generated when compiling, normally.

TRon

  • Hero Member
  • *****
  • Posts: 3822
Re: SQLite3 Date Problem
« Reply #25 on: November 19, 2024, 01:59:59 pm »
You got a point there rvk.

I always try to remember to remove any resources when uploading (but in practice 9 out of 10 times I forget as well).  :-[
I do not have to remember anything anymore thanks to total-recall.

pat03uk

  • New Member
  • *
  • Posts: 20
Re: SQLite3 Date Problem
« Reply #26 on: November 19, 2024, 02:47:31 pm »
The published project.

Pat

Handoko

  • Hero Member
  • *****
  • Posts: 5386
  • My goal: build my own game engine using Lazarus
Re: SQLite3 Date Problem
« Reply #27 on: November 19, 2024, 02:51:53 pm »
Please see my previous post:

Yes, we need an example. Bug can hide in anywhere in the code. Preferable a downloadable compile-able source code with sample data.

pat03uk

  • New Member
  • *
  • Posts: 20
Re: SQLite3 Date Problem
« Reply #28 on: November 19, 2024, 02:54:12 pm »
Sorry the database

Handoko

  • Hero Member
  • *****
  • Posts: 5386
  • My goal: build my own game engine using Lazarus
Re: SQLite3 Date Problem
« Reply #29 on: November 19, 2024, 03:41:20 pm »
Because I used Linux, I needed to modify the path to the data location. Then, it seemed to work without problem:

 

TinyPortal © 2005-2018