Recent

Author Topic: Req: DateTimeToFileDate replacement  (Read 3967 times)

WackaMold

  • New Member
  • *
  • Posts: 10
Req: DateTimeToFileDate replacement
« on: January 11, 2022, 02:52:10 am »
DateTimeToFileDate cannot handle dates after the year 2099, but I could not find any documentation about that on FPC sites. Confirmation is found at "Year must be 1980 .. 2099" Confirmation in the source is at FPC\3.2.0\Source\rtl\objpas\sysutils\dati.inc line 1249 1242.

FPC needs to be able to handle more file-dates, preferably approaching the same limits/capabilities of the target platform OS. For FileDates outside the range of DateTimeToFileDate, what set of functions is recommended? I know traditional UnixTime quits around 2038. Do I need to skip this part of the RTL and just use functions provided by the OS / Windows API? Because that is a reasonable option.

Conceptually the use-case needs a minimum resolution of whole seconds, and does not want to fuss with fractions of a second. In reality, NTFS stores file Last-Write / Last-Modified DateTime in resolution of two seconds. Annoying but oh well.

The old way is:
  FileAge
  FileDateToDateTime
  IncYear (or whatever)
  DateTimeToFileDate
  FileSetDate

What is the preferred new way?

Thaddy

  • Hero Member
  • *****
  • Posts: 11516
Re: Req: DateTimeToFileDate replacement
« Reply #1 on: January 11, 2022, 09:19:57 am »
Loosing portability is not a reasonable option, imho.
Путин преступник. Россияне дезинформированы.

wp

  • Hero Member
  • *****
  • Posts: 9571
Re: Req: DateTimeToFileDate replacement
« Reply #2 on: January 11, 2022, 10:38:19 am »
What is the reason why this function is restricted to be valid only before year 2100? Looking at the source code
Code: Pascal  [Select][+][-]
  1. Function DateTimeToFileDate(DateTime : TDateTime) : Int64;
  2.  
  3. Var YY,MM,DD,H,m,s,msec : Word;
  4.  
  5. begin
  6.   Decodedate (DateTime,YY,MM,DD);
  7.   DecodeTime (DateTime,h,m,s,msec);
  8. {$if not defined(unix) and not defined(wasi)}
  9.   If (YY<1980) or (YY>2099) then
  10.     Result:=0
  11.   else
  12.     begin
  13.     Result:=(s shr 1) or (m shl 5) or (h shl 11);
  14.     Result:=Result or longint(DD shl 16 or (MM shl 21) or (word(YY-1980) shl 25));
  15.     end;
  16. {$else unix or wasi}
  17.   Result:=LocalToEpoch(yy,mm,dd,h,m,s);
  18. {$endif unix or wasi}
  19. end;
I get the impression that the programmer simply might have thought: "I don't want to care about leap years and leap seconds after 2100 for now"
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

PascalDragon

  • Hero Member
  • *****
  • Posts: 3998
  • Compiler Developer
Re: Req: DateTimeToFileDate replacement
« Reply #3 on: January 11, 2022, 11:09:17 am »
What is the preferred new way?

The development version of FPC already provides support for FileSetDate overloads that take a TDateTime. This won't become part of the 3.2.x series however.

What is the reason why this function is restricted to be valid only before year 2100? Looking at the source code
Code: Pascal  [Select][+][-]
  1. Function DateTimeToFileDate(DateTime : TDateTime) : Int64;
  2.  
  3. Var YY,MM,DD,H,m,s,msec : Word;
  4.  
  5. begin
  6.   Decodedate (DateTime,YY,MM,DD);
  7.   DecodeTime (DateTime,h,m,s,msec);
  8. {$if not defined(unix) and not defined(wasi)}
  9.   If (YY<1980) or (YY>2099) then
  10.     Result:=0
  11.   else
  12.     begin
  13.     Result:=(s shr 1) or (m shl 5) or (h shl 11);
  14.     Result:=Result or longint(DD shl 16 or (MM shl 21) or (word(YY-1980) shl 25));
  15.     end;
  16. {$else unix or wasi}
  17.   Result:=LocalToEpoch(yy,mm,dd,h,m,s);
  18. {$endif unix or wasi}
  19. end;
I get the impression that the programmer simply might have thought: "I don't want to care about leap years and leap seconds after 2100 for now"

While DateTimeToFileDate returns a Int64 now that wasn't always the case (and was only changed so that the Unix timestamp is handled correctly), but on Windows it is in fact a 32-bit value that can only support the range 1980 to 2099, cause that is how it was originally defined in FAT and is supported by DOS and Windows (see here).

wp

  • Hero Member
  • *****
  • Posts: 9571
Re: Req: DateTimeToFileDate replacement
« Reply #4 on: January 11, 2022, 11:20:59 am »
Thanks. But still, the specs that you cite say that here are 7 bits for the years since 1980 (128 years). This means that physically the range should be extendable to 1980+128 = 2208. Not much, though...
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

PascalDragon

  • Hero Member
  • *****
  • Posts: 3998
  • Compiler Developer
Re: Req: DateTimeToFileDate replacement
« Reply #5 on: January 11, 2022, 11:55:38 am »
The documentation for FileTimeToDosDateTime indeed explicitly mentions 2107, so yes, 8 more years might be possible, but in the end one should use the new overloads once they're available.

WackaMold

  • New Member
  • *
  • Posts: 10
Re: Req: DateTimeToFileDate replacement
« Reply #6 on: January 12, 2022, 01:25:52 am »
Thanks, yeah, the restriction is to remain compatible with DOS/FAT16. Wishing for a compiler directive or other supported method for programs to drop such ancient compatibility and instead support more-modern minimum standards like FAT32 or NTFS. My intent is to support at least the same range for File-Dates that Windows does.

Found some current overloads of FileSetDate at https://gitlab.com/freepascal.org/fpc/source/-/blob/main/rtl/objpas/sysutils/sysutils.inc lines 61 and 82. Both versions call FileSetDate( ). Where is that function?

Also where can I find sources for "FileSetDate overloads that take a TDateTime"? Could not find sources in snapshot downloads :(

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1963
  • Former Delphi 1-7, 10.2 user
Re: Req: DateTimeToFileDate replacement
« Reply #7 on: January 12, 2022, 03:53:03 am »
Quote
Also where can I find sources for "FileSetDate overloads that take a TDateTime"?

Code: Text  [Select][+][-]
  1. fpc-src/rtl/win/sysutils.pp
Lazarus 2.3, FPC 3.3.1 macOS 12.3.1 x86_64 Xcode 13.3.1
Lazarus 2.3, FPC 3.3.1 macOS 12.3.1 aarch64 Xcode 13.3.1

PascalDragon

  • Hero Member
  • *****
  • Posts: 3998
  • Compiler Developer
Re: Req: DateTimeToFileDate replacement
« Reply #8 on: January 12, 2022, 09:16:02 am »
Thanks, yeah, the restriction is to remain compatible with DOS/FAT16. Wishing for a compiler directive or other supported method for programs to drop such ancient compatibility and instead support more-modern minimum standards like FAT32 or NTFS. My intent is to support at least the same range for File-Dates that Windows does.

That's why overloads are introduced. It's important to remain backwards compatible to old code. And a compiler switch can't change anything there, because pre-compiled units can not be affected by another unit.

Sidenote: FAT32 has the same restriction.

Found some current overloads of FileSetDate at https://gitlab.com/freepascal.org/fpc/source/-/blob/main/rtl/objpas/sysutils/sysutils.inc lines 61 and 82. Both versions call FileSetDate( ). Where is that function?

Those are only wrappers that wrap from name-based to handle-based FileSetDate. The real FileSetDate implementations are in the SysUtils unit of each platform.

Also where can I find sources for "FileSetDate overloads that take a TDateTime"? Could not find sources in snapshot downloads :(

Easiest is to down the full source for FPC 3.3.1 (aka main) and change Lazarus' source directory to that. Then you write a program or unit that uses the SysUtils unit and you use the FileSetDate identifier somewhere. Ctrl+Click on it which will take you to the declaration and Ctrl+Shift+Down which will take you to the implementation for the setup target.

WackaMold

  • New Member
  • *
  • Posts: 10
Re: Req: DateTimeToFileDate replacement
« Reply #9 on: January 13, 2022, 02:11:47 am »
Waitaminnit, do you mean "Lazarus directory" or "FPC source directory"? [screenshot] Neither one seemed to just-work.

Also what would I add/change on the FPC.EXE command line or in FPC.cfg for compiling with an alternate Source folder? Because I mostly use makefiles and Cmd/Bat scripts for compile+link rather than Lazarus. I'm not here for "easy" ;)

To give an idea of the flailing - Laz complained like, 'system.ppu is for the other bitness'. This might be an opportunity to completely re-install 3.2.x then slipstream-update to 3.3.1-Dev binaries and sources, so as to build native 32-bit Win32 EXEs instead of 64-bit. Cross-compiling to 64-bit or Android is nice to have, but not necessary.

 

TinyPortal © 2005-2018