TimeZoneInformation

Share your advanced PureBasic knowledge/code with the community.
Baldrick
Addict
Addict
Posts: 860
Joined: Fri Jul 02, 2004 6:49 pm
Location: Australia

TimeZoneInformation

Post by Baldrick »

There was a question in the coding section here earlier this week & it is 39 degrees here in Au atm, too hot to be bothered going outside on my Sunday, so I thought i might just throw this in here as it may be handy for someone. :)

Code: Select all

  #MinutesPerHour=60 

  Select GetTimeZoneInformation_(Tz.Time_zone_information)  
    Case #TIME_ZONE_ID_INVALID 
      Debug "TIME_ZONE_ID_INVALID" 
      End 
    Case #TIME_ZONE_ID_UNKNOWN 
      Debug "TIME_ZONE_ID_UNKNOWN" 
      End 
    Case #TIME_ZONE_ID_STANDARD 
      Debug "TIME_ZONE_ID_STANDARD"
      Offset=(Tz\Bias+Tz\StandardBias)  ; add bias's to get total minutes offset
    Case #TIME_ZONE_ID_DAYLIGHT 
      Debug "TIME_ZONE_ID_DAYLIGHT" 
      Offset=(Tz\Bias+Tz\DaylightBias)  
  EndSelect 
  Debug "////////////////////////////////////////////////////////////////////"
  With Tz ;display the individual items of the Time_zone_information structure
    Debug "Bias in minutes = "+Str(\Bias ) 
    Debug "////////////////////////////////////////////////////////////////////"
      For a=0 To 31 
        StandardName$+Chr(\StandardName[a]) 
      Next 
    Debug "StandardName = "+StandardName$
    Debug "StandardDate - i.e. revert from daylight time"
    Debug "Year should be 0 = "+Str(\StandardDate\wYear)
    Debug "Day of week this will happen - 0 for sunday to 6 for saturday = "+Str(\StandardDate\wDayOfWeek)
    Debug "which week to initiate as 1 to 5. e.g. 1st or last week in month = "+Str(\StandardDate\wDay )
    Debug "Month in which to revert to standard time = "+Str(\StandardDate\wMonth )
    StdRevert$=RSet(Str(\StandardDate\wHour),2,"0")+":"+RSet(Str(\StandardDate\wMinute),2,"0")+":"+RSet(Str(\StandardDate\wSecond),2,"0")
    Debug "Time at which Standard time reverts = "+StdRevert$  
    Debug "Extra Bias used in standard beyond 1st Bias setting = "+Str(\StandardBias) 
    Debug "////////////////////////////////////////////////////////////////////"
      For a=0 To 31 
        DaylightName$+Chr(\DaylightName[a]) 
      Next 
    Debug "DaylightName = "+DaylightName$
    Debug "DaylightDate - i.e. Start Daylight time"
    Debug "Year should be 0 = "+Str(\DaylightDate\wYear)
    Debug "Day of week this will happen - 0 for sunday to 6 for saturday = "+Str(\DaylightDate\wDayOfWeek)
    Debug "which week to initiate as 1 to 5. e.g. 1st or last week in month = "+Str(\DaylightDate\wDay)
    Debug "Month in which to switch to daylight time = "+Str(\DaylightDate\wMonth)
    DaylightSet$=RSet(Str(\DaylightDate\wHour),2,"0")+":"+RSet(Str(\DaylightDate\wMinute),2,"0")+":"+RSet(Str(\DaylightDate\wSecond),2,"0") 
    Debug "Time at which Daylight time begins = "+DaylightSet$
    Debug "Daylight Bias in minutes = "+Str(\DaylightBias) 
    Debug "////////////////////////////////////////////////////////////////////"
  EndWith    
  Debug "Current offset = "+Str(offset)+" Minutes" 
  Debug "Current offset as Hours = "+StrF(offset/#MinutesPerHour,2)+" Hours"
  Debug "////////////////////////////////////////////////////////////////////"
  lclTime=Date() ;local computer time
  utcTime=AddDate(lclTime,#PB_Date_Minute,offset) ;utc time from local time
  rtnLcltime=AddDate(utcTime,#PB_Date_Minute,-offset) ;local time again, this time using utc as base
  Debug "Local computers current time =      "+FormatDate("%hh:%ii:%ss - %dd/%mm/%yyyy",lclTime)
  Debug "based on localtime, UTC time is     "+FormatDate("%hh:%ii:%ss - %dd/%mm/%yyyy",utcTime) 
  Debug "Local time from previous UTC call  "+FormatDate("%hh:%ii:%ss - %dd/%mm/%yyyy",rtnLclTime)
  Debug "////////////////////////////////////////////////////////////////////"
  Debug ""
; Additional info pasted directly from MSDN 
;
; Bias
;     The current bias For local time translation on this computer, in minutes. 
;     The bias is the difference, in minutes, between Coordinated Universal 
;     Time (UTC) And local time. All translations between UTC And local time are 
;     based on the following formula:
; 
;     UTC = local time + bias
; 
;     This member is required.
;
; StandardName
;     A description For standard time. For example, "EST" could indicate 
;     Eastern Standard Time. The string will be returned unchanged by the 
;     GetTimeZoneInformation function. This string can be empty.
;
; StandardDate 
;     A SYSTEMTIME Structure that contains a date And local time when the transition 
;     from daylight saving time To standard time occurs on this operating system. 
;     If the time zone does Not support daylight saving time Or If the caller needs 
;     To disable daylight saving time, the wMonth member in the SYSTEMTIME Structure 
;     must be zero. If this date is specified, the DaylightDate member of this Structure 
;     must also be specified. Otherwise, the system assumes the time zone Data is invalid
;     And no changes will be applied.
; 
;     To Select the correct day in the month, set the wYear member To zero, the wHour 
;     And wMinute members To the transition time, the wDayOfWeek member To the 
;     appropriate weekday, And the wDay member To indicate the occurrence of the day 
;     of the week within the Month (1 To 5, where 5 indicates the final occurrence 
;     during the month If that day of the week does Not occur 5 times).
; 
;     Using this notation, specify 02:00 on the first Sunday in April As follows: 
;     wHour = 2, wMonth = 4, wDayOfWeek = 0, wDay = 1. Specify 02:00 on the last 
;     Thursday in October As follows: wHour = 2, wMonth = 10, wDayOfWeek = 4, wDay = 5.
; 
;     If the wYear member is Not zero, the transition date is absolute; it will only 
;     occur one time. Otherwise, it is a relative date that occurs yearly.
;
; StandardBias
;     The bias value To be used during local time translations that occur during standard 
;     time. This member is ignored If a value For the StandardDate member is Not supplied.
; 
;     This value is added To the value of the Bias member To form the bias used during 
;     standard time. In most time zones, the value of this member is zero.
;
; DaylightName
;     A description For daylight saving time. For example, "PDT" could indicate Pacific 
;     Daylight Time. The string will be returned unchanged by the GetTimeZoneInformation 
;     function. This string can be empty.
;
; DaylightDate
;     A SYSTEMTIME Structure that contains a date And local time when the transition 
;     from standard time To daylight saving time occurs on this operating system. 
;     If the time zone does Not support daylight saving time Or If the caller needs 
;     To disable daylight saving time, the wMonth member in the SYSTEMTIME Structure 
;     must be zero. If this date is specified, the StandardDate member in this Structure 
;     must also be specified. Otherwise, the system assumes the time zone Data is invalid 
;     And no changes will be applied.
; 
;     To Select the correct day in the month, set the wYear member To zero, 
;     the wHour And wMinute members To the transition time, the wDayOfWeek member 
;     To the appropriate weekday, And the wDay member To indicate the occurrence of 
;     the day of the week within the Month (1 To 5, where 5 indicates the final 
;     occurrence during the month If that day of the week does Not occur 5 times).
; 
;     If the wYear member is Not zero, the transition date is absolute; it will only 
;     occur one time. Otherwise, it is a relative date that occurs yearly.
;
; DaylightBias
;     The bias value To be used during local time translations that occur during daylight 
;     saving time. This member is ignored If a value For the DaylightDate member is Not 
;     supplied.
; 
;     This value is added To the value of the Bias member To form the bias used during 
;     daylight saving time. In most time zones, the value of this member is –60.
A couple of keywords for ppl searching: Timezone Time zone Information
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Re: TimeZoneInformation

Post by rsts »

Don't know that I'll ever use it, but thanks once again for sharing.

Very well commented..

cheers
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: TimeZoneInformation

Post by idle »

That will be handy for editing the timezone info since M$ never get daylight savings right here in NZ
Cheers
UserOfPure
Enthusiast
Enthusiast
Posts: 469
Joined: Sun Mar 16, 2008 9:18 am

Re: TimeZoneInformation

Post by UserOfPure »

I just found out today that the code used for #TIME_ZONE_ID_STANDARD should also be used when #TIME_ZONE_ID_UKNOWN is returned, otherwise the time calcs will be totally WRONG for cities that never have DST. In other words, don't ignore #TIME_ZONE_ID_UKNOWN. Trust me. :)
nigel
User
User
Posts: 62
Joined: Tue Feb 23, 2010 8:39 pm
Location: Canada

Re: TimeZoneInformation

Post by nigel »

I did a quick search of the forum on the "Timezones" topic and found this very useful thread.

Thanks to Baldrick for the useful code related to timezones. As a result of your posting, I have been able to put together the routines I need.
Your contributions are much appreciated. Thanks again, you have probably saved me at least a week of time wasted on trying to formulate
a less accurate homegrown solution.

Also a HatTip goes to UserOfPure for the valuable warning comment related to #TIME_ZONE_ID_UKNOWN case


Nigel
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4789
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: TimeZoneInformation

Post by Fangbeast »

I've found that the #TIME_ZONE_ID_INVALID comes up for some time zone selections in windows and sometimes it can be triggered by something simple as a dst box ticked or unticked for that users timezone.

Then of course, the UTC calculation is wrong because the Tz\Bias field isn't filled in that case.

Now, some users can change their O/S timezone settings to another one that is 'near' to theirs so that #TIME_ZONE_ID_INVALID isn't returned and UTC is right, but the selected timezone may not be right enough for them for other programs.

So what can be done about this?

Get the UTC time from the internet because it doesn't rely on offset calculations? Or leave the user stuck in a timezone they don't want just so that error isn't triggered?
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: TimeZoneInformation

Post by PB »

@Fangbeast: You are totally correct in that the DST checkbox of Windows
will ruin the calculations. I thought my app had timezones worked out just
right but when DST came in last month, I realized my app was an hour out
for QLD. I've yet to find a bulletproof solution. :(
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
Baldrick
Addict
Addict
Posts: 860
Joined: Fri Jul 02, 2004 6:49 pm
Location: Australia

Re: TimeZoneInformation

Post by Baldrick »

PB wrote: I thought my app had timezones worked out just
right but when DST came in last month, I realized my app was an hour out
for QLD. I've yet to find a bulletproof solution. :(
Very odd PB, I had a 2 minute play around on my machine here setting it to different timezones around Au & it all worked out spot on. Could it be that that some users don't have an up to date SP running on the systems giving this error?
( I know that sometimes when our wonderful govt's around the country go stuffing around changing start / finish times for daylight savings, M$oft dont always bother to modify their settings to cater for these govt's)

Fangbeast, could you give me the country location of the users you have found the invalid issue with so I can have a play with that?
Also, I think in your case using a time server still will not help you as it will only return the correct UTC time & your users timezone offsets will still be wrong & will still give inaccurate results.
Maybe better to go with a manual solution where in the event of getting a result of #TIME_ZONE_ID_INVALID or unknown you could pop up a window to offer them the chance to put in a manual offset themselves which would be specific to your application only & store that in the ini file. :!:
Baldrick
Addict
Addict
Posts: 860
Joined: Fri Jul 02, 2004 6:49 pm
Location: Australia

Re: TimeZoneInformation

Post by Baldrick »

PB wrote:Times will be out by 1 hour if Windows is not set to auto-switch to DST.
This will happen because Windows uses a standard offset (Tz \Bias). It uses another offset added to this main offset which is stored as 2 entries in the registry. 1. Standard offset for when daylight time is not active & 2. Daylight offest for when summer time is active. i.e. Tz\Bias+Tz\StandardBias if not summer time & Tz\Bias+Tz\DaylightBias if it is summer time ( there is actually a 3rd offset as well & I have absolutely no idea what that might be used for... )
Windows then seems to work in a way which pretty much says ' registry entry says it is summer or standard time ' AND 'Auto adjust is active or NOT'
If it is daylight time where you are & you do not have this check box ticked, Windows still picks up that it is daylight time but will ignore the extra offset for daylight time & just use the main offset as Tz \Bias+Tz\StandardBias ignoring Tz\DaylightBias. This is why you have this problem.
I am assuming you are storing your timezone info for other countries locally on your own app?
This being the case you could actually use a timer server to fix your problem I think.
Here is a little thing to help maybe help you along ( or confuse you maybe :) ) if you want to go down the road of using a time server.
http://88.191.63.41/english/viewtopic.php?f=12&t=40029

[edit] Did the last post from PB vanish or am I just going nuts???? :)
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: TimeZoneInformation

Post by PB »

I deleted my post (before your reply) because I did some better tests.
Here is my amended post, with better comments showing the problems.

> Very odd PB, I had a 2 minute play around on my machine here setting
> it to different timezones around Au & it all worked out spot on

Here's the test code I was using, that I got off these forums. The comment
on the first line was added by myself. When I run this code, it shows 23:20
for me here in Sydney, and also 23:20 for Brisbane, but it's 22:20 there. :(
The time for London is also wrong. I've just about given up getting this code
to work on any given time and date. (Hint: That's a dare to anyone reading!).

I compare the results with this: http://www.timeanddate.com/worldclock/

Code: Select all

; These tests were done in Australia DURING daylight savings.

; If "Automatically adjust clock for daylight saving changes" is
; checked in Windows, then the following code returns these values:

; Assume local time (Sydney) is 00:20.
; Brisbane returns  23:20 (correct).
; New York returns  08:20 (INCORRECT). Should be 09:20.
; London returns    13:20 (correct).
; Perth returns     21:20 (correct).
; Kathmandu returns 19:10 (correct).

; If "Automatically adjust clock for daylight saving changes" is NOT
; checked in Windows, then the following code returns these values:

; Assume local time (Sydney) is 00:20.
; Brisbane returns  00:20 (INCORRECT).
; New York returns  09:20 (correct).
; London returns    14:20 (INCORRECT). Should be 13:20.
; Perth returns     22:20 (INCORRECT). Should be 21:20.
; Kathmandu returns 19:10 (correct).

Select GetTimeZoneInformation_(Tz.Time_zone_information)
  Case #TIME_ZONE_ID_STANDARD
    offset=(Tz\Bias+Tz\StandardBias) ; get the offset between your local time & UTC time
  Case #TIME_ZONE_ID_DAYLIGHT
    offset=(Tz\Bias+Tz\DaylightBias)
EndSelect

Brisbane=600  ; UTC+10 hours = UTC+600 minutes
NewYork=-300  ; UTC-5 hours = UTC-300 minutes
London=0      ; UTC-0 hours = UTC+-0 minutes
Perth=480     ; UTC+8 hours = UTC+480 minutes
Kathmandu=345 ; UTC+5 Hours & 45 minutes = UTC+345 minutes

lclTime=Date()  ; get your local time
utcTime=AddDate(lclTime,#PB_Date_Minute,offset) ;get utc adjusted time from your local time

Debug "Local time = "+FormatDate("%hh:%ii (%dd)",lclTime) ; format the times to be readable
Debug "Brisbane time = "+FormatDate("%hh:%ii (%dd)",AddDate(utcTime,#PB_Date_Minute,Brisbane))
Debug "New York time = "+FormatDate("%hh:%ii (%dd)",AddDate(utcTime,#PB_Date_Minute,NewYork))
Debug "London time = "+FormatDate("%hh:%ii (%dd)",AddDate(utcTime,#PB_Date_Minute,London))
Debug "Perth time = "+FormatDate("%hh:%ii (%dd)",AddDate(utcTime,#PB_Date_Minute,Perth))
Debug "Kathmandu time = "+FormatDate("%hh:%ii (%dd)",AddDate(utcTime,#PB_Date_Minute,Kathmandu))
Debug "UTC time = "+FormatDate("%hh:%ii (%dd)",utcTime)
Last edited by PB on Sat Nov 06, 2010 3:32 pm, edited 4 times in total.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: TimeZoneInformation

Post by PB »

A time server is not a solution because my app will not have net access.
So, my app must rely on whatever the local time on the PC is set to, and
try to calculate world times accordingly. As you can see, I have issues. :)

I read what you said about another offset being added, so I'll have to
experiment a bit with that. The problem, my PC at my workplace does
NOT have that option to "automatically adjust the clock for DST" in
the time control panel, so it's hard to get a 100% working snippet.
What works for me at home, differs greatly from my work experience.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
Baldrick
Addict
Addict
Posts: 860
Joined: Fri Jul 02, 2004 6:49 pm
Location: Australia

Re: TimeZoneInformation

Post by Baldrick »

I just ran a test using my code from the 1st post here PB & am now thinking it seems to be a problem with the GetTimeZoneInformation_() command. If you run it with the daylight savings check box ticked, it returns as expected, but if you then untick the check box, the return result for daylight time is exactly the same as standard time right down to the name for the daylight time being the same as the standard time.
Run the code with a few different timezones set on your machine & that check box set & unset & you will see what I mean from the names it is returning. :shock:
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: TimeZoneInformation

Post by PB »

I hope it is a PureBasic bug, because I've been trying to get this to
work for over a year! :) It never occurred to me that PureBasic might
be the problem.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
Post Reply