Page 1 of 1

DAYLIGHT SAVINGS TIME "FORMULA"!! (<< yes, real formula)

Posted: Sun Mar 31, 2013 2:53 pm
by Randy Walker
... and yes, PLATFORM INDEPENDENT!!! :)

What do you do when you when your application has no access to internet and you need to relate to times in remote locations throughout the year? Traditionally you are just plain out of luck. Not any more. At least, not until the year 2100 when the next 400 year rule takes place and whacks my formula all to hell. I wont be around by then so let that be someone else's problem. :D

Barring a few regions, "Randy's DST Formula and Constants" will allow reasonably accurate relationships to most anywhere on the planet from the present until year 2100. Some locations see fit to declare DST dates on a whim without a well defined schedule so I "ball park" assignment of my constants on those areas. The threshold hour can vary for some locations so again I chose to "ball park" everyone into a single 2:00AM standard threshold hour. In short, what I am trying to say here is don't bet the farm on the results of this formula (I don't guarantee it!!) but for most intents and purposes it should prove accurate enough for most any application. Use as you like, feel free to think of me and send me lots $,$$$,$$$ if it turns out that useful to you, and please do feel free to provide working samples if you develop any improvements of your own.

One last thought. This formula *is* 100% cross platform. Visitors outside the Purebasic forum membership may also encounter this resource in their google search, but I just want to make clear, this entire post was inspired by the kind and selfless contributions I've received over the years from other members here in the Purebasic community. Thanks to them, you found this post!!!

My DST formula itself is dependent on constants, and timezone values also play a factor in relating to remote time/location so this index file will provide that information ...

Code: Select all

American Samoa:,-11.0,A
Canton Enderbury Islands:,-11.0,A
Midway Island:,-11.0,A
Niue Island:,-11.0,A
Cook Islands:,-10.0,B
French Polynesia Papeete:,-10.0,B
Johnston Island:,-10.0,B
Society Island:,-10.0,B
Tahiti:,-10.0,B
Tuamotu Island:,-10.0,B
Tubuai Island:,-10.0,B
USA Aleutian Islands:*,-10.0,b,3,14,0,0 ,11,7,0,0
USA Hawaii:,-10.0,B
Gambier Island:,-09.0,C
USA Alaska:*,-09.0,c,3,14,0,0 ,11,7,0,0
Canada Pacific:*,-08.0,d,3,14,0,0 ,11,7,0,0
Canada Yukon:,-08.0,D
Mexico Baja Calif Norte:*,-08.0,d,4,7,0,8 ,10,31,31,0
USA Pacific:*,-08.0,d,3,14,0,0 ,11,7,0,0
Canada Mountain:*,-07.0,e,3,14,0,0 ,11,7,0,0
Canada Mountain:,-07.0,E
Mexico Nayarit:*,-07.0,e,4,7,0,8 ,10,31,31,0
Mexico Sinaloa:*,-07.0,e,4,7,0,8 ,10,31,31,0
Mexico Sonora:,-07.0,E
USA Arizona:,-07.0,E
USA Mountain:*,-07.0,e,3,14,0,0 ,11,7,0,0
Belize:,-06.0,F
Canada Central:*,-06.0,f,3,14,0,0 ,11,7,0,0
Canada Central:,-06.0,F
Costa Rica:,-06.0,F
Easter Island:*,-06.0,f,9,7,0,8,4,29,30,4
El Salvador:,-06.0,F
Guatemala:,-06.0,F
Honduras:,-06.0,F
Mexico Eastern Region:*,-06.0,f,4,7,0,8 ,10,31,31,0
Mexico:,-06.0,F
Nicaragua:,-06.0,F
USA Central:*,-06.0,f,3,14,0,0 ,11,7,0,0
Bahamas:*,-05.0,g,3,14,0,0 ,11,7,0,0
Canada Eastern:*,-05.0,g,3,14,0,0 ,11,7,0,0
Canada Eastern:,-05.0,G
Cayman Islands:,-05.0,G
Colombia:,-05.0,G
Cuba:*,-05.0,g,4,7,0,8 ,11,7,0,0
Ecuador:,-05.0,G
Galapagos Islands:,-05.0,G
Haiti:*,-05.0,g,3,14,0,0 ,11,7,0,0
Jamaica:,-05.0,G
Panama:,-05.0,G
Peru:,-05.0,G
Turksand Caicos Islands:,-05.0,G
UK Turks & Caicos:*,-05.0,g,3,14,0,0 ,11,7,0,0
USA Eastern:*,-05.0,g,3,14,0,0 ,11,7,0,0
USA Indiana East:*,-05.0,g,3,14,0,0 ,11,7,0,0
Anguilla:,-04.0,H
Antigua:,-04.0,H
Argentina western prov:,-04.0,H
Aruba:,-04.0,H
Barbados:,-04.0,H
Bermuda:,-04.0,H
Bolivia:,-04.0,H
Bonaire:,-04.0,H
Brazil Acre:,-04.0,H
Brazil Central:*,-04.0,h,10,21,0,20 ,2,21,0,11
Brazil West:,-04.0,H
British Virgin Islands:,-04.0,H
Canada Atlantic:*,-04.0,h,3,14,0,0 ,11,7,0,0
Canada Atlantic:,-04.0,H
Chile:*,-04.0,h,9,14,0,24 ,3,14,0,0
Curacao:,-04.0,H
Dominica:,-04.0,H
Dominican Republic:,-04.0,H
Falkland Islands:,-04.0,H
Greenland Thule:,-04.0,H
Grenada:,-04.0,H
Grenadines:,-04.0,H
Guadeloupe:,-04.0,H
Leeward Islands:,-04.0,H
Martinique:,-04.0,H
Netherlands Antilles:*,-04.0,h,3,28,31,0 ,10,31,31,0
Nevis Montserrat:,-04.0,H
Paraguay:*,-04.0,h,10,7,0,20 ,4,14,0,8
Puerto Rico:,-04.0,H
Saba:,-04.0,H
St Christopher:,-04.0,H
St Croix:,-04.0,H
St John:,-04.0,H
St KittsNevis:,-04.0,H
St Lucia:,-04.0,H
St Maarten:,-04.0,H
St Thomas:,-04.0,H
St Vincent:,-04.0,H
Trinidadand Tobago:,-04.0,H
UK Bermuda:*,-04.0,h,3,14,0,0 ,11,7,0,0
Venezuela:,-04.0,H
Virgin Islands:,-04.0,H
Windward Islands:,-04.0,H
Argentina:,-03.0,I
Brazil East:,-03.0,I
Brazil South:*,-03.0,i,10,21,0,20 ,2,21,0,11
France Saint Pierre-Miquelon:*,-03.0,i,3,14,0,0 ,11,7,0,0
French Guiana:,-03.0,I
Greenland:*,-03.0,i,3,28,31,0 ,10,31,31,0
Guyana:,-03.0,I
St Pierre & Miquelon:,-03.0,I
Suriname:,-03.0,I
Uruguay:*,-03.0,i,10,7,0,20 ,3,14,0,0
Antarctica:,-02.0,J
Azores:,-01.0,K
Brazil Atlantic Islands:*,-01.0,k,10,21,0,20 ,2,21,0,11
Cape Verde:,-01.0,K
Greenland Scoresbysun:,-01.0,K
Guinea Bissau:,-01.0,K
Ascension:,-00.0,L
Burkina Faso:,-00.0,L
Canary Islands:,-00.0,L
Channel Islands:,-00.0,L
Coted'Ivoire:,-00.0,L
England:,-00.0,L
Faroe Island:*,-00.0,l,3,28,31,0 ,10,31,31,0
Gambia:,-00.0,L
Ghana:,-00.0,L
Greenland Danmarkshavn:,-00.0,L
Guinea:,-00.0,L
Iceland:,-00.0,L
Ireland:*,-00.0,l,3,28,31,0 ,10,31,31,0
Liberia:,-00.0,L
Madeira:,-00.0,L
Mali:,-00.0,L
Mauritania:,-00.0,L
Morocco:*,-00.0,l,4,25,30,0 ,9,26,30,0
Northern Ireland:,-00.0,L
Principe Island:,-00.0,L
Sao Tomee Principe:,-00.0,L
Scotland:,-00.0,L
Senegal:,-00.0,L
SierraLeone:,-00.0,L
St Helena:,-00.0,L
Togo:,-00.0,L
United Kingdom:*,-00.0,l,3,28,31,0 ,10,31,31,0
Wales:,-00.0,L
Western Sahara:,-00.0,L
Albania:*,+01.0,m,3,28,31,0 ,10,31,31,0
Algeria:,+01.0,M
Andorra:*,+01.0,m,3,28,31,0 ,10,31,31,0
Angola:,+01.0,M
Austria:*,+01.0,m,3,28,31,0 ,10,31,31,0
Balearic Islands:,+01.0,M
Belgium:*,+01.0,m,3,28,31,0 ,10,31,31,0
Benin:,+01.0,M
Bosnia Hercegovina:*,+01.0,m,3,28,31,0 ,10,31,31,0
Cameroon:,+01.0,M
Central African Rep:,+01.0,M
Chad:,+01.0,M
Congo:,+01.0,M
Croatia:*,+01.0,m,3,28,31,0 ,10,31,31,0
Czech Republic:*,+01.0,m,3,28,31,0 ,10,31,31,0
Dahomey:,+01.0,M
Denmark:*,+01.0,m,3,28,31,0 ,10,31,31,0
Equatorial Guinea:,+01.0,M
France:*,+01.0,m,3,28,31,0 ,10,31,31,0
Gabon:,+01.0,M
Germany:*,+01.0,m,3,28,31,0 ,10,31,31,0
Gibraltar:,+01.0,M
Hungary:*,+01.0,m,3,28,31,0 ,10,31,31,0
Italy:*,+01.0,m,3,28,31,0 ,10,31,31,0
Kosovo:*,+01.0,m,3,28,31,0 ,10,31,31,0
Liechtenstein:*,+01.0,m,3,28,31,0 ,10,31,31,0
Luxembourg:*,+01.0,m,3,28,31,0 ,10,31,31,0
Macedonia:*,+01.0,m,3,28,31,0 ,10,31,31,0
Mallorca Islands:,+01.0,M
Malta:*,+01.0,m,3,28,31,0 ,10,31,31,0
Melilla:,+01.0,M
Monaco:*,+01.0,m,3,28,31,0 ,10,31,31,0
Montenegro*,+01.0,m,3,28,31,0 ,10,31,31,0
Namibia:*,+01.0,m,9,7,0,24 ,4,7,0,8
Netherlands:*,+01.0,m,3,28,31,0 ,10,31,31,0
Niger:,+01.0,M
Nigeria:,+01.0,M
Norway:*,+01.0,m,3,28,31,0 ,10,31,31,0
Poland:*,+01.0,m,3,28,31,0 ,10,31,31,0
Portugal:*,+01.0,m,3,28,31,0 ,10,31,31,0
San Marino:*,+01.0,m,3,28,31,0 ,10,31,31,0
Serbia:*,+01.0,m,3,28,31,0 ,10,31,31,0
Slovakia:*,+01.0,m,3,28,31,0 ,10,31,31,0
Slovenia:*,+01.0,m,3,28,31,0 ,10,31,31,0
Spain:*,+01.0,m,3,28,31,0 ,10,31,31,0
Sweden:*,+01.0,m,3,28,31,0 ,10,31,31,0
Switzerland:*,+01.0,m,3,28,31,0 ,10,31,31,0
Tunisia:,+01.0,M
Vatican City:,+01.0,M
Yugoslavia:,+01.0,M
Zaire Kinshasa Mbandaka:,+01.0,M
Belarus:,+02.0,N
Botswana:,+02.0,N
Bulgaria:*,+02.0,n,3,28,31,0 ,10,31,31,0
Burundi:,+02.0,N
Cyprus:*,+02.0,n,3,28,31,0 ,10,31,31,0
Egypt:,+02.0,N
Estonia:*,+02.0,n,3,28,31,0 ,10,31,31,0
Finland:*,+02.0,n,3,28,31,0 ,10,31,31,0
Greece:*,+02.0,n,3,28,31,0 ,10,31,31,0
Israel:*,+02.0,n,3,26,31,0 ,10,7,0,20
Jordan:,+02.0,N
Latvia:*,+02.0,n,3,28,31,0 ,10,31,31,0
Lebanon:*,+02.0,n,3,28,31,0 ,10,31,31,0
Lesotho:,+02.0,N
Libya:*,+02.0,n,3,26,31,0 ,10,29,31,0
Lithuania:*,+02.0,n,3,28,31,0 ,10,31,31,0
Malawi:,+02.0,N
Moldova:*,+02.0,n,3,28,31,0 ,10,31,31,0
Moldovian Rep Pridnestrovye:,+02.0,N
Mozambique:,+02.0,N
Palestine*,+02.0,n,3,26,31,0 ,9,24,30,0
Romania:*,+02.0,n,3,28,31,0 ,10,31,31,0
Russian Federation zone one:,+02.0,N
Rwanda:,+02.0,N
South Africa:,+02.0,N
Sudan:,+02.0,N
Swaziland:,+02.0,N
Syria:*,+02.0,n,3,26,31,0 ,11,7,0,24
Turkey:*,+02.0,n,3,28,31,0 ,10,31,31,0
Ukraine:,+02.0,N
Zaire HautZaire:,+02.0,N
Zaire Kasai:,+02.0,N
Zaire Kivu:,+02.0,N
Zaire Shaba:,+02.0,N
Zambia:,+02.0,N
Zimbabwe:,+02.0,N
Azerbaijan Nagorno-Karabaj:,+03.0,O
Azerbaijan:*,+03.0,o,3,28,31,0 ,10,31,31,0
Bahrain:,+03.0,O
Djibouti:,+03.0,O
Eritrea:,+03.0,O
Ethiopia:,+03.0,O
Iraq:,+03.0,O
Kenya:,+03.0,O
Kuwait:,+03.0,O
Madagascar:,+03.0,O
Mayotte:,+03.0,O
Qatar:,+03.0,O
Russian Federation zone two:,+03.0,O
Saudi Arabia:,+03.0,O
Somalia:,+03.0,O
Tanzania:,+03.0,O
Uganda:,+03.0,O
Yemen:,+03.0,O
Iran:*,+03.5,z,3,28,0,24,9,28,0,24
Armenia:,+04.0,P
Georgia:,+04.0,P
Mauritius:,+04.0,P
Oman:,+04.0,P
Reunion:,+04.0,P
Russian Federation zone three:,+04.0,P
Seychelles:,+04.0,P
United Arab Emirates:,+04.0,P
Kyrgyzstan:,+05.0,Q
Maldives:,+05.0,Q
Pakistan:,+05.0,Q
Russian Federation zone four:,+05.0,Q
Turkmenistan:,+05.0,Q
Uzbekistan:,+05.0,Q
India:,+05.5,Z
SriLanka:,+05.5,Z
Bangladesh:,+06.0,R
Bhutan:,+06.0,R
Kazakhstan:,+06.0,R
Russian Federation zone five:,+06.0,R
Tajikistan:,+06.0,R
Cambodia:,+07.0,S
Christmas Islands:,+07.0,S
Indonesia West:,+07.0,S
Laos:,+07.0,S
Russian Federation zone six:,+07.0,S
Thailand:,+07.0,S
Vietnam:,+07.0,S
Australia Western:,+08.0,T
Brunei:,+08.0,T
China People's Rep:,+08.0,T
Hong Kong:,+08.0,T
Indonesia Central:,+08.0,T
Malaysia:,+08.0,T
Mongolia:,+08.0,T
Philippines:,+08.0,T
Russian Federation zone seven:,+08.0,T
Singapore:,+08.0,T
Taiwan:,+08.0,T
Indonesia East:,+09.0,U
Japan:,+09.0,U
Korea Dem Republic of:,+09.0,U
Korea Republic of:,+09.0,U
Palau:,+09.0,U
Russian Federation zone eight:,+09.0,U
Australia New South Wales:*,+10.0,v,10,7,0,20 ,4,7,0,8
Australia Northern Territory:,+10.0,V
Australia Queensland:,+10.0,V
Australia South:*,+10.0,v,10,7,0,20 ,4,7,0,8
Australia Tasmania:*,+10.0,v,10,7,0,20 ,4,7,0,8
Australia Victoria:*,+10.0,v,10,7,0,20 ,4,7,0,8
Australian Capital Territory:*,+10.0,v,10,7,0,20 ,4,7,0,8
Guam:,+10.0,V
Mariana Island:,+10.0,V
Northern Mariana Islands:,+10.0,V
Papua New Guinea:,+10.0,V
Russian Federation zone nine:,+10.0,V
Caroline Island:,+11.0,W
New Caledonia:,+11.0,W
New Hebrides:,+11.0,W
Ponape Island:,+11.0,W
Russian Federation zone ten:,+11.0,W
Solomon Islands:,+11.0,W
Vanuatu:,+11.0,W
Fiji:*,+12.0,x,10,31,31,0 ,1,21,0,3
Kiribati:,+12.0,X
Kusaie:,+12.0,X
Kwajalein:,+12.0,X
Marshall Islands:,+12.0,X
Nauru Republic of:,+12.0,X
New Zealand:*,+12.0,x,9,26,30,0 ,4,7,0,8
Pingelap:,+12.0,X
Russian Federation zone eleven:,+12.0,X
Tuvalu:,+12.0,X
Wake Island:,+12.0,X
Wallis Futuna Islands:,+12.0,X
Nukualofa:,+13.0,Y
Samoa:*,+13.0,y,9,26,30,0 ,4,7,0,8
And here is a simple application demo. I think it should be self-explanitory for most users...

Code: Select all

; ** ** CROSS-PLATFORM APPLICATION DEMO BASED ON MY "ONE LINE DST FORMULA" ** **  
; The "GetClientRect_" and "SetWindowLong_" APIs are the only APIs used here.
; Those APIs are only used in formating the ListIconGadget so you may want
; to design your own workaround if you want to use this code in Linux or MAC
; (or other environment).  Everything else here should be 100 cross-platform,
; easily portable to any other language.  Please observe that more than 90% what
; you see here is mearly extra code used to demonstrate the formula and guiding
; influence of my DST constants taken from the location table.

; Use of the table constants and formula themselves are very direct, however,
; to illustrate a functional application of those components to determine time
; and date of a remote location, we have to operate through 2 main stages.
; First stage is to get user input for their local time/date/place.  Then translate
; that into Greenwich (or UTC) time through Randy's Magic Formula.  The second
; stage would be to feed the second user selection (the remote location) through
; Randy's Magic Formula again to translate results of our first calculation to
; time and date for the remote location.  You'll see when you run it :)

; Also, Please note all DST crossover thresholds are performed at 2;00 AM which
; in reality is not always accurate according to some national standards.
; Additionally, I cast out areas from the main picklist that change timezones on
; the quarter hour (xx:15 xx:30 xx:45) except for Iran.  (too much nitty-gritty)


Global rc.RECT

Procedure DSTformula(YIQ,upperBase,LDM,offset) ; << Input Randy's Magic Constants given in main picklist
  ; This is the "one line formula" that for some unknown reason will not compute properly in PB ver 4.60
  ;/ DSTday = upperBase - (Int(1 + (YIQ + offset) * 5 / 4) % 7) + (7 * (Sign(upperBase/23) * Sign( Int((Int(1 + (YIQ + offset) * 5 / 4) % 7)/(upperBase+7-LDM)) )) )
  ;
  ; ... so the above "one line formula" was broken down into 3 separate lines as follows:
  DSTday = Int(1 + (YIQ + offset) * 5 / 4) % 7
  workaround = Sign(upperBase/23) * Sign( Int(DSTday/(upperBase+7-LDM)) )
  DSTday = upperBase - DSTday + (7 * workaround )
  ProcedureReturn DSTday
EndProcedure

If OpenWindow(0, 100, 100, 244, 400, "Asterisk* Regions Use DST", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ListIconGadget(0, 5, 5, 234, 288, "Location", 220, #PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection)
  GetClientRect_(GadgetID(0),rc)
  clientW= rc\right - rc\left - GetSystemMetrics_(#SM_CXVSCROLL) - 45
  SetGadgetItemAttribute(0, 0, #PB_ListIcon_ColumnWidth, clientW, 0)
  SetWindowLong_(GadgetID(0), #GWL_STYLE, GetWindowLong_(GadgetID(0), #GWL_STYLE) | #LVS_NOCOLUMNHEADER)
  
  AddGadgetColumn(0,  1, "Bias", 45)
  AddGadgetColumn(0,  2, "Zone Code", 0) ; << Ignore *My* zone code (they will not match other standards)
  AddGadgetColumn(0,  3, "Month1", 0)    ; hidden via APIs -- no need to show
  AddGadgetColumn(0,  4, "Base1", 0)     ; hidden via APIs -- no need to show
  AddGadgetColumn(0,  5, "LDM1", 0)      ; hidden via APIs -- no need to show
  AddGadgetColumn(0,  6, "Offset1", 0)   ; hidden via APIs -- no need to show
  AddGadgetColumn(0,  7, "Month2", 0)    ; hidden via APIs -- no need to show
  AddGadgetColumn(0,  8, "Base2", 0)     ; hidden via APIs -- no need to show
  AddGadgetColumn(0,  9, "LDM2", 0)      ; hidden via APIs -- no need to show
  AddGadgetColumn(0, 10, "Offset2", 0)   ; hidden via APIs -- no need to show
  
  OpenFile(0,"E:\PB_prjct\zone.dat")
  Repeat
    in$ = ReadString(0,#PB_Ascii)
    in$ = ReplaceString(in$,",",Chr(10))
    AddGadgetItem(0, -1, in$)
  Until Eof(0)
  CloseFile(0)
  
  DateGadget(1, 24, 300, 90, 25, "", Date(), #PB_Date_UpDown)
  DateGadget(2, 130, 300, 90, 25, "", Date(), #PB_Date_UpDown)
  SetWindowLong_(GadgetID(2), #GWL_STYLE, GetWindowLong_(GadgetID(2), #GWL_STYLE) | #DTS_TIMEFORMAT)
  
  ButtonGadget(3, 92, 332, 64, 25, "OK")
  StringGadget(4, 24, 364, 196, 22, "Lookie here -- ''Its magic!!!''")
  HideGadget(4,1)
  TextGadget(5, 24, 300, 196, 28, "Pick your interest above to see their local time and then click OK")
  HideGadget(5,1)
  TextGadget(6, 24, 364, 196, 28, "Pick *your* location to match your PC above, select any time and click OK.")
  ; You could replace date and time input fields with API to get local time from your own PC
  ; but I deliberately did not so I could illustrate 100% indepencance from any API calls.
  ; As it is, it can also illustrate that your initial base time/location need no be your own!!!!
  ; Any time, any place (up to year 2099) except for a few areas that change time on the quarter hours.
  
  Repeat
    EventID = WaitWindowEvent()
    
    If EventID = #PB_Event_Gadget
      
      Select EventGadget()
          
        Case 3 ; Translate user local time input
          ;/ DST CALENDAR EVENT *DAY* ACCORDING TO TABLES AND FORMULA (and PTDTRACs)
          dummy$ = GetGadgetText(1)
          month=Int(Val(StringField(dummy$, 1, "/")))
          day = Int(Val(StringField(dummy$, 2, "/")))
          year= Int(Val(StringField(dummy$, 3, "/")))
          dummy$ = GetGadgetText(2)
          hour=Int(Val(StringField(dummy$, 1, ":")))
          If FindString(dummy$,"P")
            Debug "THIS IS A PM TIME"
            hour = (Sign(Int(11/hour))*12)+hour
          Else
            Debug "THIS IS AN AM TIME"
            hour = hour-(Int(hour/12)*12)
          EndIf
          Debug "This is your tme:"
          Debug hour
          Minute = Int(Val(StringField(dummy$, 2, ":")))
          SECOND = 0
          Bias = Int(Val(GetGadgetItemText(0,GetGadgetState(0),1)))
          PTDTRAC = (Asc(GetGadgetItemText(0,GetGadgetState(0),2))/94) ; '1' = TRUE!!!
          zo = (Asc(LCase(GetGadgetItemText(0,GetGadgetState(0),2)))/(122)) * 1800 ; half a timezone
          Debug "PTDTRAC value"
          Debug PTDTRAC
          DSTeventM1 = Int(Val(GetGadgetItemText(0,GetGadgetState(0),3)))
          b = Int(Val(GetGadgetItemText(0,GetGadgetState(0),4)))
          l = Int(Val(GetGadgetItemText(0,GetGadgetState(0),5)))
          o = Int(Val(GetGadgetItemText(0,GetGadgetState(0),6)))
          DSTeventD1 = DSTformula(year,b,l,o) ; calendar day of first DST event in the year
          DSTeventM2 = Int(Val(GetGadgetItemText(0,GetGadgetState(0),7)))
          b = Int(Val(GetGadgetItemText(0,GetGadgetState(0), 8)))
          l = Int(Val(GetGadgetItemText(0,GetGadgetState(0), 9)))
          o = Int(Val(GetGadgetItemText(0,GetGadgetState(0),10)))
          DSTeventD2 = DSTformula(year,b,l,o) ; calendar day of second DST event in the year
          ;/ EVENT THRESHOLD RELATIONSHIPS -- determine 'wacked' value required by current DST, zone and hemisphere
          Specified = Date(year,month,day,hour,Minute,SECOND)
          DSTthreshold1.l = Date(year,DSTeventM1,DSTeventD1,1,59,59)
          DSTthreshold2.l = Date(year,DSTeventM2,DSTeventD2,1,59,59)
          hemisphere = Int(DSTthreshold1/DSTthreshold2) ; 0=north  1=south
          
          Debug ""
          Debug Specified
          Debug DSTeventD1
          Debug DSTeventD2
          addOne = PTDTRAC * ((Sign(Int(Specified/DSTthreshold1)*Int(DSTthreshold2/Specified))*(1-hemisphere)) + (Sign(Int(DSTthreshold2/Specified)+Int(Specified/DSTthreshold1))*hemisphere))
          wacked1 = Bias + addOne
          Debug "Adjusted UTC Offset"
          Debug wacked1
          wacked1 = wacked1 * 3600 + zo
          UTCbase = Specified - wacked1 ; remove offest values from specified location to get UTC
          ;/ QUALIFICATION
          Debug "*Your* specified place and time puts"
          Debug "the First DST event of the year on:"
          Debug FormatDate("%mm/%dd/%yyyy", DSTthreshold1)
          Debug "the Second DST event of the year on:"
          Debug FormatDate("%mm/%dd/%yyyy", DSTthreshold2)
          Debug "with Hemisphere value: ( 0=North  1=South )"
          Debug hemisphere
          Debug ""
          Debug "This is your specified date and tme:"
          Debug FormatDate("%mm/%dd/%yyyy", Specified)
          Debug FormatDate("%hh:%ii:%ss", Specified)
          Debug ""
          Debug "This is your relative UTC time (no DST):"
          Debug FormatDate("%hh:%ii:%ss", UTCbase)
          Debug addOne
          HideGadget(1,1)
          HideGadget(2,1)
          HideGadget(4,0)
          HideGadget(5,0)
          HideGadget(6,1)
          Break
          
      EndSelect
      
    EndIf
    
  Until EventID = #PB_Event_CloseWindow
  
  While EventID <> #PB_Event_CloseWindow
    EventID = WaitWindowEvent(1000)
    
    If EventID = #PB_Event_Gadget
      
      Select EventGadget()
          
        Case 3 ; Translate remote time/date for remote location(s)
          ;/ DST CALENDAR EVENT *DAY* ACCORDING TO TABLES AND FORMULA (and PTDTRACs)
          dummy$ = GetGadgetText(1)
          month=Int(Val(StringField(dummy$, 1, "/")))
          day = Int(Val(StringField(dummy$, 2, "/")))
          year= Int(Val(StringField(dummy$, 3, "/")))
          dummy$ = GetGadgetText(2)
          hour=Int(Val(StringField(dummy$, 1, ":")))
          If FindString(dummy$,"P")
            Debug "THIS IS A PM TIME"
            hour = (Sign(Int(11/hour))*12)+hour
          Else
            Debug "THIS IS AN AM TIME"
            hour = hour-(Int(hour/12)*12)
          EndIf
          Debug "This is your tme:"
          Debug hour
          Minute = Int(Val(StringField(dummy$, 2, ":")))
          SECOND = 0
          Bias = Int(Val(GetGadgetItemText(0,GetGadgetState(0),1)))
          PTDTRAC = (Asc(GetGadgetItemText(0,GetGadgetState(0),2))/(94)) ; '1' = TRUE!!!
          Debug "PTDTRAC value"
          Debug PTDTRAC
          zo = (Asc(LCase(GetGadgetItemText(0,GetGadgetState(0),2)))/(122)) * 1800 ; half a timezone
          DSTeventM1 = Int(Val(GetGadgetItemText(0,GetGadgetState(0),3)))
          b = Int(Val(GetGadgetItemText(0,GetGadgetState(0),4))) ; Base
          l = Int(Val(GetGadgetItemText(0,GetGadgetState(0),5))) ; LastDayoftheMonth
          o = Int(Val(GetGadgetItemText(0,GetGadgetState(0),6))) ; Offset
          DSTeventD1 = DSTformula(year,b,l,o) ; calendar day of first DST event in the year
          DSTeventM2 = Int(Val(GetGadgetItemText(0,GetGadgetState(0),7)))
          b = Int(Val(GetGadgetItemText(0,GetGadgetState(0), 8)))
          l = Int(Val(GetGadgetItemText(0,GetGadgetState(0), 9)))
          o = Int(Val(GetGadgetItemText(0,GetGadgetState(0),10)))
          DSTeventD2 = DSTformula(year,b,l,o) ; calendar day of second DST event in the year
          ;/ EVENT THRESHOLD RELATIONSHIPS -- determine 'wacked' value required by current DST, zone and hemisphere
          Specified = Date(year,month,day,hour,Minute,SECOND)
          DSTthreshold1.l = Date(year,DSTeventM1,DSTeventD1,1,59,59)
          DSTthreshold2.l = Date(year,DSTeventM2,DSTeventD2,1,59,59)
          hemisphere = Int(DSTthreshold1/DSTthreshold2) ; 0=north  1=south
          
          Debug ""
          Debug Specified
          Debug DSTeventD1
          Debug DSTeventD2
          addOne = PTDTRAC * ((Sign(Int(Specified/DSTthreshold1)*Int(DSTthreshold2/Specified))*(1-hemisphere)) + (Sign(Int(DSTthreshold2/Specified)+Int(Specified/DSTthreshold1))*hemisphere))
          wacked2 = Bias + addOne
          Debug "*Their* UTC Offset"
          Debug wacked2
          wacked2 = wacked2 * 3600 + zo
          Specified = UTCbase + wacked2 ; apply offest values to UTC to get *their* local time
          ;/ QUALIFICATION
          Debug "*Their* specified place and time puts"
          Debug "the First DST event of the year on:"
          Debug FormatDate("%mm/%dd/%yyyy", DSTthreshold1)
          Debug "the Second DST event of the year on:"
          Debug FormatDate("%mm/%dd/%yyyy", DSTthreshold2)
          Debug "with Hemisphere value: ( 0=North  1=South )"
          Debug hemisphere
          Debug ""
          Debug "This is *their* specified date and tme:"
          Debug FormatDate("%mm/%dd/%yyyy", Specified)
          Debug FormatDate("%hh:%ii:%ss", Specified)
          SetGadgetText(4, FormatDate("%mm/%dd/%yyyy", Specified) + "  " + FormatDate("%hh:%ii:%ss", Specified))
          Debug ""
          Debug "This is the relative UTC time (no DST):"
          Debug FormatDate("%hh:%ii:%ss", Specified - wacked2)
          Debug addOne
          HideGadget(1,1)
          HideGadget(2,1)
          HideGadget(4,0)
          HideGadget(5,0)
          HideGadget(6,1)
          
      EndSelect
      
    EndIf
    
  Wend
  
EndIf

End

Procedure Notes_on_Randys_Magic_Constants()
  ; These are Randy's custom DST constants designed to provide the main formula a working
  ; set of threshold relationships according to localized national standards.  You will
  ; see these values paired together throughout the main picklist as as columns 3-6 and
  ; 7-10 (which flip flop depending on hemisphere relationships).
  ; Alternatively, you could replace columns 3-10 in the main picklist with a single column
  ; whereby values in the column would act as an index pointing items in this table.
  ; These constants were assembled for exclusice use in Randy's Magic Formula and are only
  ; necessary for locations that use DST.
  ;/  "FIRST FRIDAY"
  ;upperBase = 7 : LDM = 0 : offset = 24   ;1st Fri Nov
  ;/  "FIRST SATURDAY"
  ;upperBase = 7 : LDM = 0 : offset = 8    ;1st Sat Sep
  ;/  "FIRST SUNDAY"
  ;upperBase = 7 : LDM = 0 : offset = 8    ;1st Sun Apr
  ;upperBase = 7 : LDM = 0 : offset = 24   ;1st Sun Sep
  ;upperBase = 7 : LDM = 0 : offset = 20   ;1st Sun Oct
  ;upperBase = 7 : LDM = 0 : offset = 0    ;1st Sun Nov
  ;/  "SECOND SUNDAY"
  ;upperBase = 14 : LDM = 0 : offset = 0   ;2nd Sun Mar
  ;upperBase = 14 : LDM = 0 : offset = 8   ;2nd Sun Apr
  ;upperBase = 14 : LDM = 0 : offset = 24  ;2nd Sun Sep
  ;upperBase = 14 : LDM = 0 : offset = 20  ;2nd Sun Oct
  ;/  "THIRD SUNDAY"
  ;upperBase = 21 : LDM = 0 : offset = 3   ;3rd Sun Jan
  ;upperBase = 21 : LDM = 0 : offset = 11  ;3rd Sun Feb
  ;upperBase = 21 : LDM = 0 : offset = 20  ;3rd Sun Oct
  ;/  "FORTH SUNDAY"
  ;upperBase = 28 : LDM = 0 : offset = 24  ;4th Sun Sep
  ;/  "LAST SUNDAY"
  ;upperBase = 28 : LDM = 31 : offset = 0  ;Las Sun Mar
  ;upperBase = 25 : LDM = 30 : offset = 0  ;Las Sun Apr
  ;upperBase = 26 : LDM = 30 : offset = 0  ;Las Sun Sep
  ;upperBase = 31 : LDM = 31 : offset = 0  ;Las Sun Oct
  ;/  "LAST SATURDAY"
  ;upperBase = 29 : LDM = 30 : offset = 4  ;Las Sat Apr
  ;/  "fORTH FRIDAY"
  ;upperBase = 28 : LDM = 0 : offset = 24  ;4th Fri Mar
  ;/  "LAST FRIDAY"
  ;upperBase = 26 : LDM = 31 : offset = 0  ;Las Fri Mar
  ;upperBase = 24 : LDM = 30 : offset = 0  ;Las Fri Sep
  ;upperBase = 29 : LDM = 31 : offset = 0  ;Las Fri Oct
EndProcedure

; NOTE: Original 'dumbs#!t' variable name was replaced above with 'PTDTRAC' (Acromym for 'People Too Dumb To Read A Clock')

Re: DAYLIGHT SAVINGS TIME "FORMULA"!! (<< yes, real formula)

Posted: Sun Mar 31, 2013 3:51 pm
by jassing
<removed, didn't intend to offend you>

Re: DAYLIGHT SAVINGS TIME "FORMULA"!! (<< yes, real formula)

Posted: Sun Mar 31, 2013 4:01 pm
by Tenaja
Very nice; thanks for sharing.

Interesting choice of variable names... :twisted:

Re: DAYLIGHT SAVINGS TIME "FORMULA"!! (<< yes, real formula)

Posted: Sun Mar 31, 2013 4:44 pm
by Randy Walker
Hi jassing ... Ummm. You did read the subject line where it says "DST Formula", right?
jassing wrote:interesting -- in windows you can query "What is my time zone?" and also get DST information; doesn't linux (&mac) have this ability? it would seem to take a lot of the work out.

Also, there's no easy way to determine one's locale --- so you'd still need to query the os to get the users codepage and *hope* that also indicates their location - and then map the code page to your list.
I usually refer to that big round thing on the wall with the hands that go round and round each day, along with the 12 page booklet looking thing on the wall next to the big round thing ... the thing with all the little square boxes and numbers, days of the week and stuff. :) Seriously though, my interest is in relating to records from around the globe from a very wide range of dates and times. I also wanted code that is (here it is again) "Cross Platform".
Don't get me wrong, it's an interesting approach, but since windows does all the hard work for you, I would that using a few api's is a better approach....
Yes, I like your sample code. (Where is that again?) Can you show me how that works in your Windows API code using "Tasmania" 17 April 2017 as your base reference point and "Cuba" as your target in question? Could be useful to someone looking for a "proprietary" Windows API based solution ... if you care to share.

Re: DAYLIGHT SAVINGS TIME "FORMULA"!! (<< yes, real formula)

Posted: Sun Mar 31, 2013 11:17 pm
by jack
what's the dumbshit value?

Re: DAYLIGHT SAVINGS TIME "FORMULA"!! (<< yes, real formula)

Posted: Mon Apr 01, 2013 4:07 pm
by Randy Walker
jack wrote:what's the dumbshit value?
Seriously? I'll assume it was a serious question so I'll give it a serious reply. It is a true/false flag that I use to indicate the nation/city/whatever (like my own) would require use of the DST formula. I've always considered DST to be infantile in origin and forced to live with the practice all my life so I thought I would apply appropriate terms to relate to it in my demo. I equate it to those people that set their alarm clock 10 minutes early so they can get 10 minutes extra sleep in the morning. Pretty much right next to brain dead. Only thing they accomplish is Pavlov's dogging themselves into being 10 minutes late for everything, outside of waking up in the morning.

BTW: The 'zo' variable is only used for Iran where they chose to shift their time zone over one half hour... hence, half a ''zone''.

Re: DAYLIGHT SAVINGS TIME "FORMULA"!! (<< yes, real formula)

Posted: Tue Apr 02, 2013 9:04 am
by MachineCode
What's with all the profanity in the code? Couldn't you have renamed the variables before posting?

Re: DAYLIGHT SAVINGS TIME "FORMULA"!! (<< yes, real formula)

Posted: Tue Apr 02, 2013 7:24 pm
by Randy Walker
@ MachineCode ... sorry about that. Is it prettier now? :?
I guess the worst of people helps bring out the worst in me, and DST is about as vulgar as it comes by my estimation.