PDA

View Full Version : Calculating Daylight Saving Time



Heckler
- 11th March 2016, 07:01
Hey group,

Been working on code to universally determine if Daylight Saving Time is or is not in effect.
Would love a second set of eyes to make sure I have not missed anything or if there is a cleaner (less code) way of doing it.

I have used the following rules as a basis...

At present, daylight saving time in the United States
begins at 2:00 a.m. on the second Sunday of March and
ends at 2:00 a.m. on the first Sunday of November

below is a shot of a spread sheet that I made to try and account for all possibilities for when a given month (March and November) might begin.
Note 1:the seven colums across represent the seven possibilities for what day of the week the month may begin on.
Note 2: the numbers next to the letter for the day of the week represent the numberd day of the week (ie sun=1, mon=2... sat=7)

8201

Here is my code...

'===========================================
'--- DST Calc (dec1 dow,dec2 mth,dec2 date) ---
dstcalc:
dst = 1 'covers Apr, May, Jun, Jul, Aug, Sep, Oct
If (mth=1) then dst = 0 'Jan
If (mth=2) then dst = 0 'Feb
If (mth=12) then dst = 0 'Dec

March:
if mth=3 then 'March
if date <8 then
dst=0
elseif (date>7 and date<15) and dow=1 and hours<2 then
dst=0 'Mar
elseif (date=8 and dow>1) then
dst=0
elseif (date=9 and dow>2) then
dst=0
elseif (date=10 and dow>3) then
dst=0
elseif (date=11 and dow>4) then
dst=0
elseif (date=12 and dow>5) then
dst=0
elseif (date=13 and dow>6) then
dst=0
endif
endif

November:
if (mth=11) then 'November
if date >7 then
dst=0
elseif (date <8 and dow=1) and hours>1 then
dst=0
elseif (date=2 and dow<3) then
dst=0
elseif (date=3 and dow<4) then
dst=0
elseif (date=4 and dow<5) then
dst=0
elseif (date=5 and dow<6) then
dst=0
elseif (date=6 and dow<7) then
dst=0
endif
endif

return


Note that the code assumes that DST is in effect (dst=1) and tries to find reasons that dst should be set to zero (dst=0)

your thoughts or ways to improve or simplify??

thanks

pedja089
- 11th March 2016, 15:21
I don't understand your tables... Column c,d,e are years? If there are, what years?
I was going to post my code for calculating DST, but in my country winter time is from last Sunday in October to last Sunday in March.
Last Sundays are on same date every 28 years, in fact all days in week are on same day in month every 28 years.
So just build 2 lookup table for 28years. And then use just Year//28 to search for date in that year.
If you look hard you can find link between day in March and day in October.
Here is code for that:


Tmp=Year 'Use less code space than Year//28 in lookup table
WHILE Tmp>27
Tmp=Tmp-28
WEND
LOOKUP Tmp,[Dates in march for 28 years],Tmp'March
IF Month=10 THEN 'October
Tmp=Tmp-4
IF Tmp<25 THEN Tmp=Tmp+7
ENDIF
It worked for me, hope that this help.
And using DST flag can complicate life, so I just move hours up or down.

Heckler
- 11th March 2016, 16:01
I don't understand your tables... Column c,d,e are years? If there are, what years?

The seven columns represent ANY year. Since in any given year, the first day of March or November could be a Sun, Mon, Tue, etc. I had to account for that fact that there are 7 POSSIBLE starting days for each month.

The reason I also show Sun=1, Mon=2, etc., is so I could ask "less than" or "greater than" questions.

I wanted this to be a universal calculation for USA.

The code will only apply for these rules...

At present, daylight saving time in the United States
begins at 2:00 a.m. on the second Sunday of March and
ends at 2:00 a.m. on the first Sunday of November
If you are in another part of the world where you have different rules (or no DST at all) then obviously this would not apply.

MichelJasmin
- 11th March 2016, 19:21
Heckler don't you get your time sync from NTP? Do you have the day of week?

If so:




Delta = Date - 7

IF Month=3 AND Day=Sunday AND (Delta>0 OR Delta<8) Then DST!



8202

By the way thank you for the ESPBasic code (http://www.picbasic.co.uk/forum/showthread.php?t=21007&p=136238#post136238)! Got some ideas...

enigma
- 11th March 2016, 22:05
Hi All
I've used this for many years, works for Europe and I suppose could be adapted for USA. DST Europe changes in March or October, last weekend of the month. The routine calculates the date in the respective month that the change occurs on.
DSTStart holds the start date for DST
DSTEnd holds the end date for DST
Year holds the year in this format e.g 2016

DSTCheck:
DSTStart = (31 - (((5*Year)/4)+ 4) mod 7)
DSTEnd = (31 - (((5*Year/4)) + 1) mod 7)
Return

That's it, Pete

pedja089
- 11th March 2016, 22:23
Can you explain how did you get this formulas?
I was searching whole net few years ago, and best I could think is to type dates for whole century find pattern, and put it in lookup table.
EDIT:
Heckler,
Just found this
http://delphiforfun.org/programs/math_topics/dstcalc.htm
Basically what Enigma wrote, but it have calculation for US.

richard
- 11th March 2016, 23:05
thanks enigma

that's very neat and tidy
for australia
#au DSTEnd 1st sunday in april = (7- (((5*Year/4)) + 4) % 7)
#au DSTStart 1st sunday in october = (7- (((5*Year/4)) + 5) % 7)

Heckler
- 12th March 2016, 02:21
@MichelJasmin

yes I do use NTP as the starting point of my calculation and I do get the date in the following format...
Thu Jan 01 00:00:00 1970

But your example would (I believe) only work if I happened to check the time on the actual day that the DST or STD time began and only be persistent if I kept track of whether DST or STD was in effect.
However in my case I may power up the clock say on March 12 or any other day of the year and need to determine the current DST/STD status.
I could probably use your example and then check to see if the current date was before or after that date.

@Enigma (Pete)

So how do you translate this bit of code into PICbasic??

DSTStart = (31 - (((5*Year)/4)+ 4) mod 7)

Does MOD 7 mean Y= X // 7 (in your example is MOD the same as the remainder?)

At this point I think I am going to give my code a spin and see how it performs.
but great discussion
Thanks all

enigma
- 12th March 2016, 10:00
Hi Heckler


So how do you translate this bit of code into PICbasic??
DSTStart = (31 - (((5*Year)/4)+ 4) mod 7)

The whole subroutine is cut directly from my PBP program and will work as is. If you want to check it write it as a small program, set Year word variable to 2016 and debug out the start and end dates.
Cheers Pete

Heckler
- 12th March 2016, 15:18
@Pete,

I'll give it a try.
I scanned through my PBP3 manual and could not find "MOD" anywhere. It doesn't show in the reserved word list either.

From the link that Pedja089 posted...

USA starting in 2007, extended DST to
begin on the 2nd Sunday in March (Day of month = 14 - (1+Y*5/4) mod 7)
and end on the 1st Sunday in November (Day of month = 7 - (1 + 5*Y/4) mod 7).

For Europe...
DST begins on the last Sunday in March (Day of month = 31 - (4+ 5*Y/4 ) mod 7)
and ends on the last Sunday in October (Day of month = 31 - (1 + 5*Y/4) mod 7)

gadelhas
- 12th March 2016, 21:46
// Remainder (Modulus)

enigma
- 12th March 2016, 22:31
Hi

I think it depends on the manual you have, mine has MOD as a reserved word in it but an earlier version does not.
Cheers Pete

Heckler
- 13th March 2016, 04:48
If anyone is wondering...

My code above does seem to test out working.
I modified my clock code to temporarily change the time to Sun March 13 01:59:45 (15 sec before DST should start) and then watched it change from 01:59 to 03:00 as it was supposed to.

Then I changed the time to Sun Nov 06 01:59:45 and watched it change from 01:59 to 01:00 as it should. :D

My nixie clock checks the date and time every morning at 05:00 and then calls my routine to test if STD/DST is in effect.
So over the next year it will be tested thoroughly.

In my case the nixie display is turned off between 10 pm and 6 am but it is still keeping time.

I'll have to ponder how to implement the above calculations into my overall code as I think I would still need to do a comparison between the current date and the calculated Start/End of DST.

I can't just abandon my baby (my version of the code) as I slaved over it for several hours :o
and it was a great challenge (as all code writing is)

But I will ponder implementing the apparently more simpler version in the near future.

thanks everyone

gadelhas
- 13th March 2016, 15:27
Dwight

How are you getting the time? GPS?

Heckler
- 13th March 2016, 17:24
gadelhas,

from an ESP8266-01 wifi module.
Which is an amazing little wifi module that is connected to my home LAN.

check out my clock project here...
http://www.picbasic.co.uk/forum/showthread.php?t=20965

and check out my description of the ESP8266-01 module here...
http://www.picbasic.co.uk/forum/showthread.php?t=20957

The little ESP module is incredibly easy to work with and really interfaces to the PIC quite easily.

If you have more questions feel free to ask or PM me.

Art
- 21st March 2016, 18:04
Unless you have a calendar you’d still want the data table anyway.
Any time you want to add or subtract time you need a calendar.

If the clock retrieves UTC time as 00:01 1st Jan 2016, and has to subtract one hour.
It has to know right down to days in month, leap years, the whole lot.

gadelhas
- 21st March 2016, 19:04
Unless you have a calendar you’d still want the data table anyway.
Any time you want to add or subtract time you need a calendar.

If the clock retrieves UTC time as 00:01 1st Jan 2016, and has to subtract one hour.
It has to know right down to days in month, leap years, the whole lot.

It's for this reason that is better work with epochtime.

Heckler
- 21st March 2016, 20:50
Unless you have a calendar you’d still want the data table anyway.
Any time you want to add or subtract time you need a calendar.

If the clock retrieves UTC time as 00:01 1st Jan 2016, and has to subtract one hour.
It has to know right down to days in month, leap years, the whole lot.

In my case I don't care about the date or year etc (other than to be used in the calculation to determine if DST is in effect or not)
and my code does not require the year for the calculation. I just needed the month, date and day of week to run through my algorithm.

My clock simply displays HH:MM, the seconds are still tracked to know when to increment the minutes.

My code checks NTP time twice a day (at 0500 and 1500) and runs the calc.
The reason I don't check it 12 hours apart is because I want it to be most accurate first thing in the morning and when I get home from work.
The display is blank between 2200 and 0600.

As noted above the ESP module give me the time in STD time and then my code determines if I need to add 1 hour or leave the time as is.

So far it seems to be working correctly.

Dave
- 21st March 2016, 21:17
Dwight, Here is the code I flashed into the ESP8266-01 I use for NTP time service. It is NOT ESP8266Basic but the standard AT command set with an added set of commands to interface with the NTP pool.org for the NTP service. It also allows for all of the other AT commands to be used. I found the ESP8255Basic to be too unstable.

Heckler
- 22nd March 2016, 00:02
@Art

Unless you have a calendar you’d still want the data table anyway.
Any time you want to add or subtract time you need a calendar.

If the clock retrieves UTC time as 00:01 1st Jan 2016, and has to subtract one hour.
It has to know right down to days in month, leap years, the whole lot.

In my case, my clock does not keep track of the date or year.
I only use the Day of Week, Month and Date to determine if DST is or is not in effect.

My ESP module gives me those three items along with the HH:MM:SS and my algorithm then determines whether or not I need to add 1 hour to the provided STD time. After that I don't bother with anything other than HH:MM:SS.

My code above seems to be working good so far and I did test for DST/STD crossing in both directions and it seems to work.

@Dave
Thanks for sharing your code, I'll take a look at it.

So far my module running ESPbasic has been running solid with this code loaded in the ESP module...

'================================================= ==========
'--- This is the code running on the ESP8266-01 module ---
'================================================= ==========
'''memclear
'''cls
'''timesetup(-7,0)
'''baudrate 9600
'''serialtimeout 2000
'''delay 1000
'''button "Exit" [Exit]
'''timer 100 [PicSer]
'''wait
''''
'''[PicSer]
'''serialflush
'''input picin
'''picin = mid(picin,1,5)
'''if picin == "Time?" then gosub [gettime]
'''wait
''''
'''[gettime]
'''bla = time()
'''dy = mid(bla,1,3) 'dow
'''mh = mid(bla,5,3) 'month
'''dd = mid(bla,9,2) 'date
'''hh = mid(bla,12,2) 'hour
'''mm = mid(bla,15,2) 'min
'''ss = mid(bla,18,2) 'sec
'''yr = mid(bla,21,4) 'year
''''
'''if dy == "Sun" then dow = "1/"
'''if dy == "Mon" then dow = "2/"
'''if dy == "Tue" then dow = "3/"
'''if dy == "Wed" then dow = "4/"
'''if dy == "Thu" then dow = "5/"
'''if dy == "Fri" then dow = "6/"
'''if dy == "Sat" then dow = "7/"
''''
'''if mh == "Jan" then mth = "01/"
'''if mh == "Feb" then mth = "02/"
'''if mh == "Mar" then mth = "03/"
'''if mh == "Apr" then mth = "04/"
'''if mh == "May" then mth = "05/"
'''if mh == "Jun" then mth = "06/"
'''if mh == "Jul" then mth = "07/"
'''if mh == "Aug" then mth = "08/"
'''if mh == "Sep" then mth = "09/"
'''if mh == "Oct" then mth = "10/"
'''if mh == "Nov" then mth = "11/"
'''if mh == "Dec" then mth = "12/"
''''
'''picout = dow & mth
'''picout = picout & dd
'''picout = picout & "/"
'''picout = picout & hh
'''picout = picout & mm
'''picout = picout & ss
''''
'''serialprintln picout
'''return
''''
'''[Exit]
'''end

If you want to see the code running on the PIC in the clock just search the forum for "nixie".

I wonder if you were having problems with a certain version of the ESPbasic OS. Mike did seem to have a couple of versions that were a bit unreliable.

My ESP module is currently running Version 1.67 of the OS. I think he is up over 1.8x now and I think it is working pretty well also.
I think the problems were in the 1.7x region of his revisions. (not exact)

The ESPbasic is based (I believe) on the arduion IDE and the arduino/ESP foundation so if you are competent at the arduino C-like language then that is probably a good way to go.

I just like the built in IDE of the ESPbasic and it's (for me) easy to understand and no external IDE required.

thanks all!