|
|
View previous topic :: View next topic |
Author |
Message |
Guest
|
Daylight Savings... |
Posted: Thu Nov 05, 2009 10:49 am |
|
|
Hi All,
Does anyone have a handy routine that will take the year and determine the days that Daylight Savings Time will begin and end?
Thanks!
Joe |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Thu Nov 05, 2009 1:57 pm |
|
|
This was my code but you may find a better way to do it.
Code: |
////////////////////////////////////////////////////////////////////
/////// special look up tables
//////////////////////////////////////////////////////////////////////
const int8 table[12]= {6,2,2,5,0,3,5,1,4,6,2,4}; /// for day of week
const int8 months[12]={30,28,30,30,31,30,31,30,30,31,30,31}; // days in month
////////// globals//////////////////////////////////////
//// day mth template
struct d_m{
int8 day;
int8 mth;
};
/// declare storage for daylight start
union {
int8 reg[2];
struct d_m date;
} dls_start;
/// declare storage for daylight end
union {
int8 reg[2];
struct d_m date;
} dls_end;
//////////////////////////////// functions ///////////////////////////////////////////
int8 day_of_week(int8 day,int8 mth,int8 yr)
{int8 val,tmp;
//// yr is last two digits Ex 2007 is 07
/// mth is month Jan=1.....Dec=12
/// explanation
/// 365 days is 1 mod 7 so a non leap year begins on the next day of the week
// to the prior year and another day added if a leap year
// the calc is ahead of itself during an actual leap year hence the
// adjusting down for jan and feb in a leap year
// the table is derived as follows 1/1/01 is a monday so yr=1 day=1 +x mod 7
// has to yield 1 (Monday) so table[0] must be 6 ( 6+1+1=8 and 8 mod 7 is 1)
val=yr+yr/4; /// leap year adj good 2007 to 2099
val=val+table[mth-1]; /// table contains modulo 7 adjustments for mths
val=val+day; /// actual day 1..31
tmp=yr%4;
if(tmp==0) { //leap year
if(mth<3) val=val-1; /// adjust jan and feb down one for leap year
}
val=val%7; /// modulo 7
if(val==0)val=7;
/// val is now the day of week 1=Mon .......7=Sun
return(val);
/// ex dls_start.date.mth=11 dls_start.date.day=1 Nov 1st Sunday
////// ex dls_end.date.mth=03 dls_end.date.day=2 March 2nd Sunday
///// code assumes switch always occurs on a Sunday
int8 dls_adj(int8 hr,int8 day,int8 mth,int8 yr) /// requires day_of_week
{
int8 adj,dow,start_day,start_mth,end_day,end_mth,sun;
//// local clock springs forward in march falls back in Nov
/// for Florida Nov thru March local time is GMT -5 otherwiseo GMT-4
/// adj to local time is 0 for March thru Nov and 1 Nov thru March
/// dls_start.date.mth is 11=Nov dls_start.date.day is 1 =1st sun
/// dls_end.date.mth is 03=Mar dls_end.date.day is 2 =2nd sun
/// start and end are relative to GMT-4 ( the day the -1 adj starts)
/// the day the (-1 adjustment ends) this is opposite to DLS
/// starting in Mar and ending in Nov
/// If Daylight saving law changes then dls_start.date.mth and dls_start.day are adjusted
/// For 2008 it is the 1st Sun in Nov and 2nd Sun in Mar
/// get dow for Nov 1 in current year
start_mth=dls_start.date.mth;
sun=dls_start.date.day;
dow=day_of_week(1,start_mth,yr); // d/m/y Sun is 7
start_day=sun*7-dow+1;
/// 1st Sun in Nov dls_start.date.day=1 dls_start.date.mth=11
/// ex if Nov 1 is a Sun then dow is 7 so 1st Sun is Nov 1
/// a Wed then dow is 3 so 1st Sun is Nov 5
///
/// get dow for Mar 1 in current year
end_mth=dls_end.date.mth;
sun=dls_end.date.day;
dow=day_of_week(1,end_mth,yr); // d/m/y Sun is 7
dow=day_of_week(1,end_mth,yr); // d/m/y Sun is 7
end_day=sun*7-dow+1;
/// 2nd Sun in Mar dls_start.date.day=2 dls_start.date.mth=3
/// ex if Mar 1 is a Sun then dow is 7 so 2nd Sun is Mar 8
/// a Wed then dow is 3 so 2nd Sun is Mar 12
///
//// now if the DS1307 date is less than end_mth/end_day Mar 2nd Sun
/// the dsl adj is 1
/// also if the Ds307 date is greater than start_mth/end_mth Now 1st Sun
/// the dsl adj is 1
adj=0;
if(mth<end_mth) adj=1;
if( (mth==end_mth) && (day<end_day))adj=1;
if((mth==end_mth) && (day==end_day) && (hr<2)) adj=1;
if(mth>start_mth) adj=1;
if( (mth==start_mth) && (day>start_day)) adj=1;
if( (mth==start_mth) && (day==start_day) && (hr>2)) adj=1;
dls_start.date.day=start_day;
dls_start.date.mth=start_mth;
dls_end.date.day=end_day;
dls_end.date.mth=end_mth;
return(adj);
|
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Nov 05, 2009 4:56 pm |
|
|
Beware that the date for Daylight Savings Time is not the same in all countries. For Europe the given example program would calculate the wrong date and has to be modified for this.
What we did in our data logging application was to ignore DST and only log in UTC-time. The PC processing the data can then decide on how to handle DST. This made things a lot easier and more user friendly. For example, what to do when the clock is set back one hour? Throw away the already recorded data? Or create a double as high number of counted items? Implementing this on the PC allowed for the user to choose as he wishes. |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Thu Nov 05, 2009 9:21 pm |
|
|
Code: |
/// ex dls_start.date.mth=11 dls_start.date.day=1 Nov 1st Sunday
////// ex dls_end.date.mth=03 dls_end.date.day=2 March 2nd Sunday
///// code assumes switch always occurs on a Sunday |
I don't know the specifics of European DST but if it starts on any sunday in any month then the variables dls_start.date.day and dls_start_.date.mth would work. dls_start.date.day is 1 if its the first Sunday 2 if the second and 3 if its the third similarly for end dates. Now if European DST starts after the first full moon in November it wont work. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Fri Nov 06, 2009 6:36 am |
|
|
European DST start last sunday in march and ends last sunday in october, fortunately you don't need a moon calendar, but possbly the gregorian formula to calculate the day of week, if not provided by your system clock/RTC. |
|
|
John Morley
Joined: 09 Aug 2004 Posts: 97
|
|
Posted: Fri Nov 13, 2009 10:56 am |
|
|
Hi All,
Here is some code I use for calculating the start and end days of daylight savings here in the US:
Code: |
int8 iBeginDay;
int8 iEndDay;
int16 iYear;
iBeginDay = (14 - ((iYear * 5) / 4 + 1) % 7);
iEndDay = iBeginDay - 7;
|
In the US, daylight savings always begins on the 2nd Sunday in March, and ends on the 1st Sunday in November. The code above will determine the day in March, and the day in November when this will occur.
BTW, I've tested it until 2099, so if the definition of daylight savings does not change, this code is good for a long while.....
John _________________ John Morley |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|