DateX::GetLocalDate for all OS

Share your advanced PureBasic knowledge/code with the community.
User avatar
mk-soft
Always Here
Always Here
Posts: 5389
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

DateX::GetLocalDate for all OS

Post by mk-soft »

GetLocalDate returns the date and time as a simple structure.
We can use this for QDate, Date64, etc

Testet with:
- MacOS X86 and X64. Thanks to Wilbert
- Linux X86 and X64
- Window X86 and X64

Update v1.02
- Update structure type year to word

Update v1.03
- Added GetSystemDate(...)

Update v1.04
- Change MacOS GetSystemDate(..). Thanks to Wilbert
- Cleanup code

Code: Select all

;-TOP
; Comment: Get loacl date and time as simple structure
; Author : mk-soft
; Version: v1.04
; Created: 26.07.2016
; Updated: 

; ***************************************************************************************

DeclareModule DateX
  
  Structure sDateTime
    Year.w
    Month.b
    Day.b
    Hour.b
    Minute.b
    Second.b
  EndStructure
  
  Declare GetLocalDate(*DateTime.sDateTime)
  Declare GetSystemDate(*DateTime.sDateTime)
  
EndDeclareModule

Module DateX
  
  EnableExplicit
  
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_MacOS
      ; Thanks to Wilbert
      ImportC ""
        CFAbsoluteTimeGetCurrent.d()
        CFCalendarCopyCurrent()
        CFCalendarSetTimeZone(*calendar, tz)
        CFCalendarDecomposeAbsoluteTime(*calendar, at.d, componentDesc.p-ascii, *year, *month, *day, *hour, *minute, *second)
        CFTimeZoneCreateWithTimeIntervalFromGMT(*allocator, ti.d)
      EndImport

      Procedure GetLocalDate(*DateTime.sDateTime)
        Protected Year.integer, Month.integer, Day.integer, Hour.integer, Minute.integer, Second.integer
        Protected timeCurrent.d = CFAbsoluteTimeGetCurrent()
        Protected *CurrentCalendar = CFCalendarCopyCurrent()
        CFCalendarDecomposeAbsoluteTime(*CurrentCalendar, timeCurrent, "yMdHms", @Year, @Month, @Day, @Hour, @Minute, @Second)
        CFRelease_(*CurrentCalendar)
        With *DateTime
          \Year = Year\i
          \Month = Month\i
          \Day = Day\i
          \Hour = Hour\i
          \Minute = Minute\i
          \Second = Second\i
        EndWith
      EndProcedure
      
      Procedure GetSystemDate(*DateTime.sDateTime)
        Protected Year.integer, Month.integer, Day.integer, Hour.integer, Minute.integer, Second.integer
        Protected timeCurrent.d
        Protected *CurrentCalendar = CFCalendarCopyCurrent()
        Protected *TimeZoneGMT = CFTimeZoneCreateWithTimeIntervalFromGMT(#Null, 0.0)
        CFCalendarSetTimeZone(*CurrentCalendar, *TimeZoneGMT)
        timeCurrent = CFAbsoluteTimeGetCurrent()
        CFCalendarDecomposeAbsoluteTime(*CurrentCalendar, timeCurrent, "yMdHms", @Year, @Month, @Day, @Hour, @Minute, @Second)
        CFRelease_(*CurrentCalendar)
        CFRelease_(*TimeZoneGMT)
        With *DateTime
          \Year = Year\i
          \Month = Month\i
          \Day = Day\i
          \Hour = Hour\i
          \Minute = Minute\i
          \Second = Second\i
        EndWith
      EndProcedure
      
    CompilerCase #PB_OS_Linux
      
      Structure tm
        tm_sec.l  ;	int	seconds after the minute	0-61*
        tm_min.l  ;	int	minutes after the hour	0-59
        tm_hour.l ;	int	hours since midnight	0-23
        tm_mday.l ;	int	day of the month	1-31
        tm_mon.l  ;	int	months since January	0-11
        tm_year.l ;	int	years since 1900	
        tm_wday.l ;	int	days since Sunday	0-6
        tm_yday.l ;	int	days since January 1	0-365
        tm_isdst.l;	int	Daylight Saving Time flag	
      EndStructure
      
      Procedure GetLocalDate(*DateTime.sDateTime)
        Protected time.i, *timeinfo.tm
        time_(@time)
        *timeinfo = localtime_(@time)
        With *DateTime
          \Year = *timeinfo\tm_year + 1900
          \Month = *timeinfo\tm_mon + 1
          \Day = *timeinfo\tm_mday
          \Hour = *timeinfo\tm_hour
          \Minute = *timeinfo\tm_min
          \Second = *timeinfo\tm_sec
        EndWith
        
      EndProcedure
      
      Procedure GetSystemDate(*DateTime.sDateTime)
        Protected time.i, *timeinfo.tm
        time_(@time)
        *timeinfo = gmtime_(@time)
        With *DateTime
          \Year = *timeinfo\tm_year + 1900
          \Month = *timeinfo\tm_mon + 1
          \Day = *timeinfo\tm_mday
          \Hour = *timeinfo\tm_hour
          \Minute = *timeinfo\tm_min
          \Second = *timeinfo\tm_sec
        EndWith
        
      EndProcedure
      
    CompilerCase #PB_OS_Windows
      
      Procedure GetLocalDate(*DateTime.sDateTime)
        Protected timeinfo.systemtime
        GetLocalTime_(timeinfo)
        With *DateTime
          \Year = timeinfo\wYear
          \Month = timeinfo\wMonth
          \Day = timeinfo\wDay
          \Hour = timeinfo\wHour
          \Minute = timeinfo\wMinute
          \Second = timeinfo\wSecond
        EndWith
      EndProcedure
      
      Procedure GetSystemDate(*DateTime.sDateTime)
        Protected timeinfo.systemtime
        GetSystemTime_(timeinfo)
        With *DateTime
          \Year = timeinfo\wYear
          \Month = timeinfo\wMonth
          \Day = timeinfo\wDay
          \Hour = timeinfo\wHour
          \Minute = timeinfo\wMinute
          \Second = timeinfo\wSecond
        EndWith
      EndProcedure
      
  CompilerEndSelect
  
  ; -----------------------------------------------------------------------------------
  
EndModule

; ***************************************************************************************

CompilerIf #PB_Compiler_IsMainFile
  
  ;-Test
  
  Define DateTime.DateX::sDateTime
  
  DateX::GetLocalDate(DateTime)
  Debug "*** Local Date ***"
  With DateTime
    Debug "Year: " + Str(\year)
    Debug "Month: " + Str(\month)
    Debug "Day: " + Str(\day)
    Debug "Hour: " + Str(\hour)
    Debug "Minute: " + Str(\minute)
    Debug "Second: " + Str(\second)
  EndWith
  
  DateX::GetSystemDate(DateTime)
  Debug "*** System Date ***"
  With DateTime
    Debug "Year: " + Str(\year)
    Debug "Month: " + Str(\month)
    Debug "Day: " + Str(\day)
    Debug "Hour: " + Str(\hour)
    Debug "Minute: " + Str(\minute)
    Debug "Second: " + Str(\second)
  EndWith
  
CompilerEndIf
Last edited by mk-soft on Wed Jul 26, 2017 8:27 pm, edited 3 times in total.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Little John
Addict
Addict
Posts: 4527
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: DateX::GetLocalDate for all OS

Post by Little John »

mk-soft wrote:GetLocalDate returns the date and time as a simple structure.
Another way to do the same, not surprisingly also cross-platform. ;-)

Code: Select all

EnableExplicit

Structure DateTime
   Year.w
   Month.b
   Day.b
   Hour.b
   Minute.b
   Second.b
EndStructure

Procedure GetDateTime (*dt.DateTime)
   Protected now.i = Date()
   
   With *dt
      \Year   = Year(now)
      \Month  = Month(now)
      \Day    = Day(now)
      \Hour   = Hour(now)
      \Minute = Minute(now)
      \Second = Second(now)
   EndWith
EndProcedure


;-- Demo
Define now.DateTime

GetDateTime(now)

With now
   Debug "Year  : " + \Year
   Debug "Month : " + \Month
   Debug "Day   : " + \Day
   Debug "Hour  : " + \Hour
   Debug "Minute: " + \Minute
   Debug "Second: " + \Second
EndWith
Last edited by Little John on Tue Jul 25, 2017 8:02 pm, edited 1 time in total.
User avatar
Sicro
Enthusiast
Enthusiast
Posts: 538
Joined: Wed Jun 25, 2014 5:25 pm
Location: Germany
Contact:

Re: DateX::GetLocalDate for all OS

Post by Sicro »

Nice, that we now have a working solution for MacOS.

The Linux code does not use thread-safe functions. Look into the Date64 code for thread-safe functions.

But why do not we all work together and create one complete date library with extended date range.
Little John wrote:Another way to do the same, not surprisingly also cross-platform.
-- code --
Your code uses the PB-Date library and therefore has the same date limits.

Edit: Code removed from the quote.
Last edited by Sicro on Sat Jul 29, 2017 10:13 pm, edited 2 times in total.
Image
Why OpenSource should have a license :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (syntax color scheme) :: RegEx-Engine (compiles RegExes to NFA/DFA)
Manjaro Xfce x64 (Main system) :: Windows 10 Home (VirtualBox) :: Newest PureBasic version
Little John
Addict
Addict
Posts: 4527
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: DateX::GetLocalDate for all OS

Post by Little John »

Sicro wrote:
Little John wrote:<Almost full quote not quoted again.>
Your code uses the PB-Date library and therefore has the same date limits.
These codes are not for date calculations, but for yielding the current date and time.
When a program should be compiled now or in the near future, and is supposed not to be re-compiled until 19.01.2038, then it certainly would be advantageous to use mk-soft's code. Otherwise, people (especially beginners) might like using a simpler code that only utilises built-in PB functions.
Last edited by Little John on Tue Jul 25, 2017 8:00 pm, edited 1 time in total.
User avatar
mk-soft
Always Here
Always Here
Posts: 5389
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: DateX::GetLocalDate for all OS

Post by mk-soft »

I've lost my way ...
The year should be a type word

Update v1.02
- Bugfix

Update v1.03
- Added GetSystemDate(...)

Small trick with MacOS. Perhaps find a better way...

P.S.
Or the type for the year should be a long?
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
Sicro
Enthusiast
Enthusiast
Posts: 538
Joined: Wed Jun 25, 2014 5:25 pm
Location: Germany
Contact:

Re: DateX::GetLocalDate for all OS

Post by Sicro »

Little John wrote:These codes are not for date calculations, but for yielding the current date and time.
Yes, I know that, of course.
In the first post, however, mk-soft mentions "QDate" and "Date64" and so I strongly believe that with his code, he wants to enrich the existing codes that perform date calculations.

I did not say your code is useless.
Image
Why OpenSource should have a license :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (syntax color scheme) :: RegEx-Engine (compiles RegExes to NFA/DFA)
Manjaro Xfce x64 (Main system) :: Windows 10 Home (VirtualBox) :: Newest PureBasic version
Little John
Addict
Addict
Posts: 4527
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: DateX::GetLocalDate for all OS

Post by Little John »

Sicro wrote:
Little John wrote:These codes are not for date calculations, but for yielding the current date and time.
Yes, I know that, of course.
In the first post, however, mk-soft mentions "QDate" and "Date64"
Yes, I know.
Anyway, as I wrote, the limit of PB's built-in function for the current date will not be reached until 19.01.2038 -- regardless for what purpose the current date will be used.
walbus
Addict
Addict
Posts: 929
Joined: Sat Mar 02, 2013 9:17 am

Re: DateX::GetLocalDate for all OS

Post by walbus »

Thanks for sharing
Last edited by walbus on Wed Jul 26, 2017 8:34 pm, edited 2 times in total.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: DateX::GetLocalDate for all OS

Post by wilbert »

mk-soft wrote:Update v1.03
- Added GetSystemDate(...)

Small trick with MacOS. Perhaps find a better way...
You can set the timezone of the calendar to GMT but it's about the same amount of code so maybe not really a better way.

Code: Select all

ImportC ""
  CFCalendarCopyCurrent()
  CFCalendarDecomposeAbsoluteTime(calendar, at.d, componentDesc.p-ascii, 
                                  *year, *month, *day, *hour, *min, *sec)
  CFCalendarSetTimeZone(calendar, tz)
  CFTimeZoneCreateWithTimeIntervalFromGMT(allocator, ti.d)
EndImport

CurrentCalendar.i = CFCalendarCopyCurrent()
TimeZoneGMT.i = CFTimeZoneCreateWithTimeIntervalFromGMT(#Null, 0)
CFCalendarSetTimeZone(CurrentCalendar, TimeZoneGMT)
CFCalendarDecomposeAbsoluteTime(CurrentCalendar, CFAbsoluteTimeGetCurrent_(), "yMdHms", 
                                @year, @month, @day, @hour, @min, @sec)
CFRelease_(TimeZoneGMT)
CFRelease_(CurrentCalendar)

Debug "Year: " + Str(year)
Debug "Month: " + Str(month)
Debug "Day: " + Str(day)
Debug "Hour: " + Str(hour)
Debug "Minute: " + Str(min)
Debug "Second: " + Str(sec)
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
Sicro
Enthusiast
Enthusiast
Posts: 538
Joined: Wed Jun 25, 2014 5:25 pm
Location: Germany
Contact:

Re: DateX::GetLocalDate for all OS

Post by Sicro »

Little John wrote:Anyway, as I wrote, the limit of PB's built-in function for the current date will not be reached until 19.01.2038 -- regardless for what purpose the current date will be used.
I understand you very well.

2038 - 2017 = 21 years
Perhaps it's silly to think of a program that would be in use after compiling so long. I have however experienced that some companies use their programs for a very long time. Some companies still use DOS programs for their warehouse management.

As I see here we have the same opinion:
Little John wrote:When a program should be compiled now or in the near future, and is supposed not to be re-compiled until 19.01.2038, then it certainly would be advantageous to use mk-soft's code.
Now we are back at my real question from above:
Sicro wrote:But why do not we all work together and create one complete date library with extended date range.
Last edited by Sicro on Wed Jul 26, 2017 5:30 pm, edited 2 times in total.
Image
Why OpenSource should have a license :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (syntax color scheme) :: RegEx-Engine (compiles RegExes to NFA/DFA)
Manjaro Xfce x64 (Main system) :: Windows 10 Home (VirtualBox) :: Newest PureBasic version
User avatar
mk-soft
Always Here
Always Here
Posts: 5389
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: DateX::GetLocalDate for all OS

Post by mk-soft »

Update v1.04
- Change MacOS GetSystemDate(..). Thanks to Wilbert
- Cleanup code

@Wilbert,
I think your code is better :wink:

@All,
The problem is which basis for the sequential time for Purebasic take.
Windows automation takes Double as days, Mac is Double in seconds, Linux takes whole numbers.
Have not found an alternative for 'time _ (...) and' localtime (...) for Linux yet.

(Sorry, goggle translator)
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: DateX::GetLocalDate for all OS

Post by wilbert »

mk-soft wrote:The problem is which basis for the sequential time for Purebasic take.
Windows automation takes Double as days, Mac is Double in seconds, Linux takes whole numbers.
I'm not exactly sure what you mean by the PureBasic sequential time. :?
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
mk-soft
Always Here
Always Here
Posts: 5389
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: DateX::GetLocalDate for all OS

Post by mk-soft »

I mean internal timeformat for Purebasic. Sorry, my english :(

I think double for seconds since jear x.

P.S.
We can simple calculate to
- MacOS : Jan 1 2001 00:00:00 GMT; Double; Resulution 1 sencond
- Windows Filetime: January 1, 1601; Quad; Resulution 100 nanoseconds
- Windows Variant VT_Date: January 1, 100; Double; Resulution Days and part of day
- Linux: Unix time format or other
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: DateX::GetLocalDate for all OS

Post by wilbert »

mk-soft wrote:MacOS : Jan 1 2001 00:00:00 GMT; Double; Resulution 1 second
According to what I read online, the resolution is microseconds (it's based on gettimeofday).

Code: Select all

Structure timeval
  tv_sec.i
  tv_usec.l
EndStructure

gettimeofday_(@t.timeval, #Null)
at.d = 1e-6 * t\tv_usec + t\tv_sec - 978307200

Debug at; same as CFAbsoluteTimeGetCurrent_()
Windows (x64)
Raspberry Pi OS (Arm64)
Post Reply