25 October 2016

100 years of DST dates for Europe: 2016-2116

As described in an earlier post, I want to try implementing automatic DST switch over in my homemade clocks. At least in those that have a firmware inside.

The plan is to hardcode the switch over date, keep track of DST status in non-volatile EEPROM and check whether a change should be made at power up. The array starts on year 2016, so in case the RTC is reset the firmware must ensure it is taken immediately to year 2016.

So, according to the packing format described in the earlier post, this is how 100 years of DST dates for Europe looks like:

int DSTdays[100] = {
0x25, // 2016-03-27 to 2016-10-30
0x14, // 2017-03-26 to 2017-10-29
0x03, // 2018-03-25 to 2018-10-28
0x62, // 2019-03-31 to 2019-10-27
0x40, // 2020-03-29 to 2020-10-25
0x36, // 2021-03-28 to 2021-10-31
0x25, // 2022-03-27 to 2022-10-30
0x14, // 2023-03-26 to 2023-10-29
0x62, // 2024-03-31 to 2024-10-27
0x51, // 2025-03-30 to 2025-10-26
0x40, // 2026-03-29 to 2026-10-25
0x36, // 2027-03-28 to 2027-10-31
0x14, // 2028-03-26 to 2028-10-29
0x03, // 2029-03-25 to 2029-10-28
0x62, // 2030-03-31 to 2030-10-27
0x51, // 2031-03-30 to 2031-10-26
0x36, // 2032-03-28 to 2032-10-31
0x25, // 2033-03-27 to 2033-10-30
0x14, // 2034-03-26 to 2034-10-29
0x03, // 2035-03-25 to 2035-10-28
0x51, // 2036-03-30 to 2036-10-26
0x40, // 2037-03-29 to 2037-10-25
0x36, // 2038-03-28 to 2038-10-31
0x25, // 2039-03-27 to 2039-10-30
0x03, // 2040-03-25 to 2040-10-28
0x62, // 2041-03-31 to 2041-10-27
0x51, // 2042-03-30 to 2042-10-26
0x40, // 2043-03-29 to 2043-10-25
0x25, // 2044-03-27 to 2044-10-30
0x14, // 2045-03-26 to 2045-10-29
0x03, // 2046-03-25 to 2046-10-28
0x62, // 2047-03-31 to 2047-10-27
0x40, // 2048-03-29 to 2048-10-25
0x36, // 2049-03-28 to 2049-10-31
0x25, // 2050-03-27 to 2050-10-30
0x14, // 2051-03-26 to 2051-10-29
0x62, // 2052-03-31 to 2052-10-27
0x51, // 2053-03-30 to 2053-10-26
0x40, // 2054-03-29 to 2054-10-25
0x36, // 2055-03-28 to 2055-10-31
0x14, // 2056-03-26 to 2056-10-29
0x03, // 2057-03-25 to 2057-10-28
0x62, // 2058-03-31 to 2058-10-27
0x51, // 2059-03-30 to 2059-10-26
0x36, // 2060-03-28 to 2060-10-31
0x25, // 2061-03-27 to 2061-10-30
0x14, // 2062-03-26 to 2062-10-29
0x03, // 2063-03-25 to 2063-10-28
0x51, // 2064-03-30 to 2064-10-26
0x40, // 2065-03-29 to 2065-10-25
0x36, // 2066-03-28 to 2066-10-31
0x25, // 2067-03-27 to 2067-10-30
0x03, // 2068-03-25 to 2068-10-28
0x62, // 2069-03-31 to 2069-10-27
0x51, // 2070-03-30 to 2070-10-26
0x40, // 2071-03-29 to 2071-10-25
0x25, // 2072-03-27 to 2072-10-30
0x14, // 2073-03-26 to 2073-10-29
0x03, // 2074-03-25 to 2074-10-28
0x62, // 2075-03-31 to 2075-10-27
0x40, // 2076-03-29 to 2076-10-25
0x36, // 2077-03-28 to 2077-10-31
0x25, // 2078-03-27 to 2078-10-30
0x14, // 2079-03-26 to 2079-10-29
0x62, // 2080-03-31 to 2080-10-27
0x51, // 2081-03-30 to 2081-10-26
0x40, // 2082-03-29 to 2082-10-25
0x36, // 2083-03-28 to 2083-10-31
0x14, // 2084-03-26 to 2084-10-29
0x03, // 2085-03-25 to 2085-10-28
0x62, // 2086-03-31 to 2086-10-27
0x51, // 2087-03-30 to 2087-10-26
0x36, // 2088-03-28 to 2088-10-31
0x25, // 2089-03-27 to 2089-10-30
0x14, // 2090-03-26 to 2090-10-29
0x03, // 2091-03-25 to 2091-10-28
0x51, // 2092-03-30 to 2092-10-26
0x40, // 2093-03-29 to 2093-10-25
0x36, // 2094-03-28 to 2094-10-31
0x25, // 2095-03-27 to 2095-10-30
0x03, // 2096-03-25 to 2096-10-28
0x62, // 2097-03-31 to 2097-10-27
0x51, // 2098-03-30 to 2098-10-26
0x40, // 2099-03-29 to 2099-10-25
0x36, // 2100-03-28 to 2100-10-31
0x25, // 2101-03-27 to 2101-10-30
0x14, // 2102-03-26 to 2102-10-29
0x03, // 2103-03-25 to 2103-10-28
0x51, // 2104-03-30 to 2104-10-26
0x40, // 2105-03-29 to 2105-10-25
0x36, // 2106-03-28 to 2106-10-31
0x25, // 2107-03-27 to 2107-10-30
0x03, // 2108-03-25 to 2108-10-28
0x62, // 2109-03-31 to 2109-10-27
0x51, // 2110-03-30 to 2110-10-26
0x40, // 2111-03-29 to 2111-10-25
0x25, // 2112-03-27 to 2112-10-30
0x14, // 2113-03-26 to 2113-10-29
0x03, // 2114-03-25 to 2114-10-28
0x62, // 2115-03-31 to 2115-10-27
0x40, // 2116-03-29 to 2116-10-25
};

The row index is computed as (year - 2016). Each row is a BCD representation of intoDST and outFromDST dates, minus 25 (since the last Sunday always falls on 25th or later). So, 0x62 means on 31st (of March) we enter DST and on 27th (of October) we leave DST.

In order to avoid endless loop or complicated date jumps, the firmware will not change the time before 3 AM.

And this is the Perl script that produces the array above. It can be adapted to suit different DST rules, if a reader wants to follow my route.

#!/usr/bin/perl
use strict ;
use warnings ;
use DateTime ;

print "int DSTdays[100] = {\n";
for my $y( 2016..2116 ){

   my $ONdate = DateTime->last_day_of_month( year => $y ,
         month => 3 ) ;
   while ( $ONdate->dow != 7 ) {
      $ONdate = $ONdate->subtract( days => 1 ) ;
   }
   my $OFFdate = DateTime->last_day_of_month( year => $y ,
         month => 10 ) ;
   while ( $OFFdate->dow != 7 ) {
      $OFFdate = $OFFdate->subtract( days => 1 ) ;
   }
   my $ONymd = ($ONdate->day - 25) ;
   my $ONymdx = $ONdate->ymd ;
   #print "$ONymd;" ;
   my $OFFymd = $OFFdate->day - 25;
   my $OFFymdx = $OFFdate->ymd ;
   #print "$OFFymd\n" ;
   print "0x".$ONymd.$OFFymd.", // ".$ONymdx." to ".$OFFymdx."\n";
}
print "};\n";


Last but not least, this should be implemented in a clock firmware. And DST will be over in 4 days...

No comments: