Author Topic: Calling the GetTimeZoneInformation function in QB64  (Read 2886 times)

0 Members and 1 Guest are viewing this topic.

Offline EricE

  • Forum Regular
  • Posts: 114
    • View Profile
Calling the GetTimeZoneInformation function in QB64
« on: March 28, 2020, 05:54:09 pm »
Here is a program that calls the Windows API function GetTimeZoneInformation

Code: QB64: [Select]
  1. TYPE SYSTEMTIME
  2.   wMonth AS _UNSIGNED INTEGER
  3.   wDayOfWeek AS _UNSIGNED INTEGER
  4.   wMinute AS _UNSIGNED INTEGER
  5.   wSecond AS _UNSIGNED INTEGER
  6.   wMilliseconds AS _UNSIGNED INTEGER
  7.  
  8. TYPE TIME_ZONE_INFORMATION
  9.   Bias AS LONG
  10.   StandardName AS STRING*64 'WCHAR      StandardName[32];
  11.   StandardDate AS SYSTEMTIME
  12.   StandardBias AS LONG
  13.   DaylightName AS STRING*64 'WCHAR      DaylightName[32];
  14.   DaylightDate AS SYSTEMTIME
  15.   DaylightBias AS LONG
  16.  
  17. ' Function prototype:
  18. ' DWORD GetTimeZoneInformation( LPTIME_ZONE_INFORMATION lpTimeZoneInformation);
  19.   FUNCTION GetTimeZoneInformation& (BYVAL lpTimeZoneInformation AS _UNSIGNED _OFFSET)
  20.  
  21. DIM tz_info AS TIME_ZONE_INFORMATION
  22.  
  23. retval& = GetTimeZoneInformation(_OFFSET(tz_info))
  24.  
  25. PRINT "Returned Value = ";retval&
  26. PRINT "TZ INFO"
  27. PRINT " Bias = ";tz_info.Bias
  28. PRINT " StandardName = ";tz_info.StandardName
  29. PRINT " Standard Date"
  30. PRINT "   wYear        = ";tz_info.StandardDate.wYear
  31. PRINT "   wMonth       = ";tz_info.StandardDate.wMonth
  32. PRINT "   wDayOfWeek   = ";tz_info.StandardDate.wDayOfWeek
  33. PRINT "   wDay         = ";tz_info.StandardDate.wDay
  34. PRINT "   wHour        = ";tz_info.StandardDate.wHour
  35. PRINT "   wMinute      = ";tz_info.StandardDate.wMinute
  36. PRINT "   wSecond      = ";tz_info.StandardDate.wSecond
  37. PRINT "   wMillisecons = ";tz_info.StandardDate.wMilliseconds
  38. PRINT " StandardBias = ";tz_info.StandardBias
  39. PRINT "Press any key to continue"
  40. PRINT " DaylightName = ";tz_info.DaylightName
  41. PRINT " DaylightDate"
  42. PRINT "   wYear        = ";tz_info.DaylightDate.wYear
  43. PRINT "   wMonth       = ";tz_info.DaylightDate.wMonth
  44. PRINT "   wDayOfWeek   = ";tz_info.DaylightDate.wDayOfWeek
  45. PRINT "   wDay         = ";tz_info.DaylightDate.wDay
  46. PRINT "   wHour        = ";tz_info.DaylightDate.wHour
  47. PRINT "   wMinute      = ";tz_info.DaylightDate.wMinute
  48. PRINT "   wSecond      = ";tz_info.DaylightDate.wSecond
  49. PRINT "   wMillisecons = ";tz_info.DaylightDate.wMilliseconds
  50. PRINT " DaylightBias = ";tz_info.DaylightBias

Petr has written a program that calls the GetTimeZoneInformation function in a manner different than specified in the Microsoft documention.

Here is my version of Petr's program.

Code: QB64: [Select]
  1.     SUB GetTimeZoneInformation (a AS INTEGER)
  2.  
  3. tz& = GETTIMEZONE
  4. PRINT "Your time zone is:"; tz&  
  5.  
  6. FUNCTION GETTIMEZONE
  7.     DIM b AS INTEGER
  8.        
  9.     GetTimeZoneInformation b
  10.     PRINT "GetTimeZoneInformation = ";b
  11.        
  12.     GETTIMEZONE = b / -60 'so it return time zone in hours (+1 for Prague)

There is certainly a big difference between  using an INTEGER rather than an  _OFFSET as a function's parameter.
Also, notice that Petr's method treats GetTimeZoneInformation as a SUB rather than a FUNCTION.

Why does Petr's method work in that it returns a correct value for the time zone Bias value?


« Last Edit: March 29, 2020, 07:43:28 am by EricE »

Offline EricE

  • Forum Regular
  • Posts: 114
    • View Profile
Re: Calling the GetTimeZoneInformation function in QB64
« Reply #1 on: March 29, 2020, 01:23:18 am »
I have the answer.
The Time Zone Bias INTEGER value (it really should be a LONG) that is returned is correct because it is the first field in the Time Zone structure and the value fits in an INTEGER.
All the other fields don't make it out of the call to the GetTimeZoneInformation function and are lost.

Here is my debug code, if anyone wants to see it.
I changed the GetTimeZoneInformation parameter from an INTEGER which it was in Petr's code to a fixed string type, STRING*1000 to make room for the returned data.

Code: QB64: [Select]
  1. TYPE SYSTEMTIME
  2.   wMonth AS _UNSIGNED INTEGER
  3.   wDayOfWeek AS _UNSIGNED INTEGER
  4.   wMinute AS _UNSIGNED INTEGER
  5.   wSecond AS _UNSIGNED INTEGER
  6.   wMilliseconds AS _UNSIGNED INTEGER
  7.  
  8. TYPE TIME_ZONE_INFORMATION
  9.   Bias AS LONG
  10.   StandardName AS STRING*64 'WCHAR      StandardName[32];
  11.   StandardDate AS SYSTEMTIME
  12.   StandardBias AS LONG
  13.   DaylightName AS STRING*64 'WCHAR      DaylightName[32];
  14.   DaylightDate AS SYSTEMTIME
  15.   DaylightBias AS LONG
  16.  
  17.  
  18.     ' SUB GetTimeZoneInformation (a as INTEGER)
  19.     SUB GetTimeZoneInformation (a as string)
  20.  
  21. DIM SHARED tz_info AS TIME_ZONE_INFORMATION
  22.  
  23. tz& = GETTIMEZONE
  24. PRINT "Your time zone is:"; tz&  
  25.  
  26. FUNCTION GETTIMEZONE
  27.     'DIM b AS INTEGER
  28.         DIM b AS STRING*1000
  29.        
  30.     GetTimeZoneInformation b
  31.         '----
  32.         m=_MEM(b)
  33.         _MEMGET m, m.OFFSET, Bias%
  34.     PRINT "GetTimeZoneInformation = ";Bias%
  35.     '----  
  36.     GETTIMEZONE = Bias% / -60 'so it return time zone in hours (+1 for Prague)
  37.         '----
  38.         _MEMGET m, m.OFFSET, tz_info
  39.         Print_TimeZone_Info tz_info
  40.         _MEMFREE m
  41.         '----
  42.  
  43. SUB Print_TimeZone_Info( tzi AS TIME_ZONE_INFORMATION)
  44.   PRINT "TZ INFO"
  45.   PRINT " Bias = ";tz_info.Bias
  46.   print " StandardName = ";tzi.StandardName
  47.   PRINT " Standard Date"
  48.   PRINT "   wYear        = ";tzi.StandardDate.wYear
  49.   PRINT "   wMonth       = ";tzi.StandardDate.wMonth
  50.   PRINT "   wDayOfWeek   = ";tzi.StandardDate.wDayOfWeek
  51.   PRINT "   wDay         = ";tzi.StandardDate.wDay
  52.   PRINT "   wHour        = ";tzi.StandardDate.wHour
  53.   PRINT "   wMinute      = ";tzi.StandardDate.wMinute
  54.   PRINT "   wSecond      = ";tzi.StandardDate.wSecond
  55.   PRINT "   wMillisecons = ";tzi.StandardDate.wMilliseconds
  56.   PRINT " StandardBias = ";tzi.StandardBias
  57.   PRINT "Press any key to continue"
  58.   PRINT " DaylightName = ";tzi.DaylightName
  59.   PRINT " DaylightDate"
  60.   PRINT "   wYear        = ";tzi.DaylightDate.wYear
  61.   PRINT "   wMonth       = ";tzi.DaylightDate.wMonth
  62.   PRINT "   wDayOfWeek   = ";tzi.DaylightDate.wDayOfWeek
  63.   PRINT "   wDay         = ";tzi.DaylightDate.wDay
  64.   PRINT "   wHour        = ";tzi.DaylightDate.wHour
  65.   PRINT "   wMinute      = ";tzi.DaylightDate.wMinute
  66.   PRINT "   wSecond      = ";tzi.DaylightDate.wSecond
  67.   PRINT "   wMillisecons = ";tzi.DaylightDate.wMilliseconds
  68.   PRINT " Daylig
  69. END SUB
« Last Edit: March 29, 2020, 01:25:05 am by EricE »

Offline EricE

  • Forum Regular
  • Posts: 114
    • View Profile
Re: Calling the GetTimeZoneInformation function in QB64
« Reply #2 on: March 29, 2020, 01:23:42 am »
Why do I make all this work for myself?

Offline EricE

  • Forum Regular
  • Posts: 114
    • View Profile
Re: Calling the GetTimeZoneInformation function in QB64
« Reply #3 on: March 29, 2020, 05:07:21 am »
Here is the debug program using _MEM's unreferenced syntax.

This debug code shows that GetTimeZoneInformation writes to memory past the INTEGER output parameter!

Code: QB64: [Select]
  1. TYPE SYSTEMTIME
  2.   wMonth AS _UNSIGNED INTEGER
  3.   wDayOfWeek AS _UNSIGNED INTEGER
  4.   wMinute AS _UNSIGNED INTEGER
  5.   wSecond AS _UNSIGNED INTEGER
  6.   wMilliseconds AS _UNSIGNED INTEGER
  7.  
  8. TYPE TIME_ZONE_INFORMATION
  9.   Bias AS LONG
  10.   StandardName AS STRING*64 'WCHAR      StandardName[32];
  11.   StandardDate AS SYSTEMTIME
  12.   StandardBias AS LONG
  13.   DaylightName AS STRING*64 'WCHAR      DaylightName[32];
  14.   DaylightDate AS SYSTEMTIME
  15.   DaylightBias AS LONG
  16.  
  17.  
  18.     SUB GetTimeZoneInformation (a as INTEGER)
  19.     'SUB GetTimeZoneInformation (a as string)
  20.  
  21. DIM SHARED tz_info AS TIME_ZONE_INFORMATION
  22.  
  23. tz& = GETTIMEZONE
  24. PRINT "Your time zone is:"; tz&  
  25.  
  26. FUNCTION GETTIMEZONE
  27.     DIM b AS INTEGER
  28.         'DIM b AS STRING*1000
  29.        
  30.     GetTimeZoneInformation b
  31.         '----
  32.         'm=_MEM(b)
  33.         m = _MEM(_OFFSET(b), 1000) ' _MEM Unsecure syntax
  34.        
  35.         _MEMGET m, m.OFFSET, Bias%
  36.     PRINT "GetTimeZoneInformation = ";Bias%
  37.     '----  
  38.     GETTIMEZONE = Bias% / -60 'so it return time zone in hours (+1 for Prague)
  39.         '----
  40.         _MEMGET m, m.OFFSET, tz_info
  41.         Print_TimeZone_Info tz_info
  42.         _MEMFREE m
  43.         '----
  44.  
  45. SUB Print_TimeZone_Info( tzi AS TIME_ZONE_INFORMATION)
  46.   PRINT "TZ INFO"
  47.   PRINT " Bias = ";tz_info.Bias
  48.   print " StandardName = ";tzi.StandardName
  49.   PRINT " Standard Date"
  50.   PRINT "   wYear        = ";tzi.StandardDate.wYear
  51.   PRINT "   wMonth       = ";tzi.StandardDate.wMonth
  52.   PRINT "   wDayOfWeek   = ";tzi.StandardDate.wDayOfWeek
  53.   PRINT "   wDay         = ";tzi.StandardDate.wDay
  54.   PRINT "   wHour        = ";tzi.StandardDate.wHour
  55.   PRINT "   wMinute      = ";tzi.StandardDate.wMinute
  56.   PRINT "   wSecond      = ";tzi.StandardDate.wSecond
  57.   PRINT "   wMillisecons = ";tzi.StandardDate.wMilliseconds
  58.   PRINT " StandardBias = ";tzi.StandardBias
  59.   PRINT "Press any key to continue"
  60.   PRINT " DaylightName = ";tzi.DaylightName
  61.   PRINT " DaylightDate"
  62.   PRINT "   wYear        = ";tzi.DaylightDate.wYear
  63.   PRINT "   wMonth       = ";tzi.DaylightDate.wMonth
  64.   PRINT "   wDayOfWeek   = ";tzi.DaylightDate.wDayOfWeek
  65.   PRINT "   wDay         = ";tzi.DaylightDate.wDay
  66.   PRINT "   wHour        = ";tzi.DaylightDate.wHour
  67.   PRINT "   wMinute      = ";tzi.DaylightDate.wMinute
  68.   PRINT "   wSecond      = ";tzi.DaylightDate.wSecond
  69.   PRINT "   wMillisecons = ";tzi.DaylightDate.wMilliseconds
  70.   PRINT " Daylig
  71. END FUNCTION
  72.  
« Last Edit: March 29, 2020, 07:44:06 am by EricE »