Recent

Author Topic: String Long time format to DateTime  (Read 11983 times)

Xatrix

  • New Member
  • *
  • Posts: 15
String Long time format to DateTime
« on: June 05, 2021, 06:35:38 pm »
Hi all

I have a problem with this string '2021-05-22T13:57:49.191021Z"
Is any routine to convert this to correct DateTime Format ??

I'm sorry.,but stuck with this ;-(

wp

  • Hero Member
  • *****
  • Posts: 11857
Re: String Long time format to DateTime
« Reply #1 on: June 05, 2021, 07:22:23 pm »
Normally you can solve this with the ScanDateTime function in DateUtils where you provide for each digit the corresponding date/time code, and quote the non-digit characters:

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. uses
  4.   SysUtils, DateUtils;
  5.  
  6. const
  7.   s = '2021-05-22T13:57:49.191534Z';
  8. var
  9.   dt: TDateTime;
  10. begin
  11.   dt := ScanDateTime('yyyy"-"mm"-"dd"T"hh":"nn":"ss"."zzz???"Z"', s);
  12.   WriteLn(DateToStr(dt) + ' ' + FormatDateTime('hh:nn:ss.zzz', dt));
  13.   ReadLn;
  14. end.

The problem here is that the ScanDateTime precision ends with milliseconds. But the time part in your string has microsecond resolution. To make ScanDateTime accept this you must use the '?' wildcard symbol for the additional digits. Of course, this still does not give you microsecond resolution. For this, there is no ready-made conversion function. If you really need this ultra-precision you must scan the input string for the decimal point and extract the fractional second manually:

Code: Pascal  [Select][+][-]
  1. const
  2.   s = '2021-05-22T13:57:49.191534Z';
  3. var
  4.   dt: TDateTime;
  5.   p: Integer;
  6.   fs: Double;  // fractional seconds
  7.   n: Integer;
  8. begin
  9.   p := pos('.', s);
  10.   val(copy(s, p, Length(s)-p), fs, n);
  11.   dt := ScanDateTime('yyyy"-"mm"-"dd"T"hh":"nn":"ss???????"Z"', s) + fs*OneSecond;
  12.   WriteLn(dt);

Xatrix

  • New Member
  • *
  • Posts: 15
Re: String Long time format to DateTime
« Reply #2 on: June 05, 2021, 07:37:02 pm »
Thx !!

I try do this with old style ( From Delphi ).

Thank You again !!!!

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: String Long time format to DateTime
« Reply #3 on: June 05, 2021, 08:33:57 pm »
Hi!

You DateTimeString is ISO 8601. There is a function for that in the unit DateUtils:

Code: Pascal  [Select][+][-]
  1. Function ISO8601ToDate(const DateString: string; ReturnUTC : Boolean = True): TDateTime;

Winni

Xatrix

  • New Member
  • *
  • Posts: 15
Re: String Long time format to DateTime
« Reply #4 on: June 06, 2021, 10:02:49 am »
Hi!

You DateTimeString is ISO 8601. There is a function for that in the unit DateUtils:

Code: Pascal  [Select][+][-]
  1. Function ISO8601ToDate(const DateString: string; ReturnUTC : Boolean = True): TDateTime;

Winni

Code: Pascal  [Select][+][-]
  1. const
  2.   dt1 = '2021-05-22T13:57:49.191021Z';
  3.   dt2 = '2021-05-22T13:57:49.191Z';
  4.  
  5. var
  6.  dt : TDateTime;
  7.  
  8. begin
  9.  
  10.   dt:=Now(); // initialize
  11.   dt := ISO8601ToDate(dt1,true);
  12.  
  13.   ShowMessage(DateTimeToStr(dt));
  14. end;        
  15.  
in dt1 I get an error :
EConvertError with message :
Invalid date/timestamp : "2021-05-22T13:57:49.191021Z"
dt2  give me :
2021-05-22 13:57:49

But in this case ,i get more than 3 digits after seconds.
I think, we can close this thread.

PS. In Borland C++ i found ISO8601TimeToDateTime and this works perfectly.

Thank You all for help.

wp

  • Hero Member
  • *****
  • Posts: 11857
Re: String Long time format to DateTime
« Reply #5 on: June 06, 2021, 01:25:05 pm »
Since Delphi can handle your input string in ISO8601ToDate()  I submitted a bug report with patch: https://bugs.freepascal.org/view.php?id=38968
« Last Edit: June 06, 2021, 01:59:49 pm by wp »

dbannon

  • Hero Member
  • *****
  • Posts: 2786
    • tomboy-ng, a rewrite of the classic Tomboy
Re: String Long time format to DateTime
« Reply #6 on: June 06, 2021, 02:06:14 pm »
I had the same problem in my app.  (edit:) The ISO8601 std says you can have any number of digits after the dec point.

So, I look for a content after the dec point, if its there, I strip it off, convert whats left using TryISO8601ToDate() and then add the striped part back into the result. To do that, I pack it out to micro seconds, convert that number of microseconds to a datetime and add it. Messy but necessary sometimes.

                        // Will take a range of ISO-8601 dates and convert to DateTime, either local or UTC
                        // Uses TryISO8601ToDate for all greater than uSec, then adds uSec back in.
                        // If ReturnUTC is false returns local time

see MyTryISO8601ToDate() in https://github.com/tomboy-notes/tomboy-ng/blob/master/source/tb_utils.pas

Davo

P.S. Glad that WP has reported it but that will take a long time to happen.
« Last Edit: June 06, 2021, 02:11:40 pm by dbannon »
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

wp

  • Hero Member
  • *****
  • Posts: 11857
Re: String Long time format to DateTime
« Reply #7 on: June 06, 2021, 04:02:58 pm »
Michael already has applied the patch, but it is scheduled to go into FPC 4.0.0. So, let's wait until next decade...

wp

  • Hero Member
  • *****
  • Posts: 11857
Re: String Long time format to DateTime
« Reply #8 on: June 06, 2021, 04:31:25 pm »
I had a chance to look at your patch before the site went down for me over here..

Wouldn't it be wiser to use POS in locating the separators instead of assuming they are living at fixed locations?

I realize people are to follow the standard but not every does to the letter.
Just wanted to keep as much of the other code to reduce the risk of regressions. But I am convinced that the function requires a complete rewrite anyway, because according to the wiki, ISO8601 allows also strings without separators...

dbannon

  • Hero Member
  • *****
  • Posts: 2786
    • tomboy-ng, a rewrite of the classic Tomboy
Re: String Long time format to DateTime
« Reply #9 on: June 07, 2021, 02:09:47 am »
You do have to wonder just how many of the possible legal variations of ISO8601 this function can support.  But concentrating on just the (optional) part after the decimal point.

A decimal fraction may be added to the lowest order time element present, in any of these representations. A decimal mark, either a comma or a dot (following ISO 80000-1 according to ISO 8601:1-2019,[25] which does not stipulate a preference except within International Standards, but with a preference for a comma according to ISO 8601:2004)[26] is used as a separator between the time element and its fraction. .....There is no limit on the number of decimal places for the decimal fraction.

I am rather upset about the decimal mark being either a dot or comma, with comma preferred.  And "any number" of places. And after any (final) stanza, not just seconds. So, milli-minutes, micro-days etc ....

Obviously, extreme far right decimal places need to be ignored (not generate an exception).  The definition of a file format I use has seven digits after a decimal dot and I need to convert all of them.

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: String Long time format to DateTime
« Reply #10 on: June 07, 2021, 08:53:27 am »
Michael already has applied the patch, but it is scheduled to go into FPC 4.0.0. So, let's wait until next decade...

4.0.0 is merely the next available release that we have on Mantis. I personally never set a target release until its clear what the next one really is...

dsiders

  • Hero Member
  • *****
  • Posts: 1052
Re: String Long time format to DateTime
« Reply #11 on: June 07, 2021, 09:29:23 pm »
Just wanted to keep as much of the other code to reduce the risk of regressions. But I am convinced that the function requires a complete rewrite anyway, because according to the wiki, ISO8601 allows also strings without separators...

It appears there are already conditional tests to handle values without separators. In both date and time conversions.

I took a stab at reconciling the new code and the docs. An html file with the updated topics is attached. If it looks accurate, I can submit a doc patch.

Preview Lazarus 3.99 documentation at: https://dsiders.gitlab.io/lazdocsnext

wp

  • Hero Member
  • *****
  • Posts: 11857
Re: String Long time format to DateTime
« Reply #12 on: June 07, 2021, 11:27:02 pm »
I took a stab at reconciling the new code and the docs. An html file with the updated topics is attached. If it looks accurate, I can submit a doc patch.
Wow, what a work... Thanks for the effort.

Did you check all the sample output?

If I did not miss it, the essence of the recent patch is not mentioned: the fractional part of the seconds can consist of any number of digits now, not just three (as indicated by the ".zzz"), and the decimal separator can also be a comma.

dsiders

  • Hero Member
  • *****
  • Posts: 1052
Re: String Long time format to DateTime
« Reply #13 on: June 07, 2021, 11:46:15 pm »
I took a stab at reconciling the new code and the docs. An html file with the updated topics is attached. If it looks accurate, I can submit a doc patch.

Did you check all the sample output?

If I did not miss it, the essence of the recent patch is not mentioned: the fractional part of the seconds can consist of any number of digits now, not just three (as indicated by the ".zzz"), and the decimal separator can also be a comma.

I have not because I am hesitant to start fiddling with RTL on my dev machine.

The accompanying text spells out the precision and decimal point changes. I had to put some number of decimals in the examples. I suppose I could vary the number of digits to make the point.
Preview Lazarus 3.99 documentation at: https://dsiders.gitlab.io/lazdocsnext

wp

  • Hero Member
  • *****
  • Posts: 11857
Re: String Long time format to DateTime
« Reply #14 on: June 08, 2021, 12:42:35 am »
I have not because I am hesitant to start fiddling with RTL on my dev machine.
I am attaching a simple demo for a variety of test cases. It prints out the ISO-formatted input string and the decoded date/time, or "Error" if the conversion was not successful. There are still some "Error"s indicating that there is still work to be done. Especially for me because my patch obviously broke the non-separator dates with fractional seconds which works in FPC 3.2 but fails in current trunk (after the patch)...

The accompanying text spells out the precision and decimal point changes. I had to put some number of decimals in the examples. I suppose I could vary the number of digits to make the point.
I see it now. I think it's ok.

 

TinyPortal © 2005-2018