Shop OBEX P1 Docs P2 Docs Events
RTC and DST — Parallax Forums


Is there any way to automatically adjust a RTC (DS3231) for daylight savings time?
Even if not the exact day but within a week or so



  • Only by resetting the time, or adjusting it after reading when in DST. That chip does not automatically adjust. If you want one that does, the ISL12022MA is a better choice, and also has a built-in TCXO.
  • Thanks Sapphire

    I guess I can figure out how to program the Prop to do the same. I was hoping there might be an easier way!

  • Here is the code I use to do the DST adjustment. It's from a Basic Stamp program, but you could easily convert it to Spin.
    I2CIN SDA,DS1307_Address,SPSEC,[SPSTR 7]	' read clock into SPRAM
    FOR y = SPSEC TO SPYR			' 7 bytes (second to year)
      GET y,x : PUT y,$7 & x.NIB1 * 10 + x.NIB0	' convert from BCD to decimal and put back in SPRAM
    GET SPHR,hour : GET SPMIN,minute : GET SPSEC,second	' get time
    IF hour = 2 AND minute = 0 AND second = 0 THEN	' check for Daylight Saving Time
      GET SPMON,month : GET SPDAY,day : GET SPDOW,dow 	' get month, day and dow from SPRAM
      IF month = 3 AND dow = 7 THEN	' March and Sunday
        IF day >= 8 AND day < 15 THEN	' second week
          WRITE E_DST,1		' set DST in EEPROM
          hour = 3			' set hour to 3
        ENDIF					'
      ENDIF						'
      IF month = 11 AND dow = 7 THEN	' November and Sunday
        IF day < 8 THEN			' first week
          READ E_DST,dst		' get DST from EEPROM
          IF dst THEN 		' DST is set
            WRITE E_DST,0	' clear DST in EEPROM
            hour = 1		' set hour to 1
          ENDIF				'
        ENDIF					'
      ENDIF						'
      IF hour <> 2 THEN  			' time was changed
        PUT SPHR,hour			' set new hour SPRAM
        I2COUT SDA,DS1307_Address,SPHR,[hour]	' set new hour in DS1307 clock
      ENDIF   					' no BCD conversion necessary as hour can only be 1 or 3
    ENDIF							'
    READ E_DST,dst					' read DST bit from EEPROM
    RETURN							' done
  • TorTor Posts: 2,010
    IMO it's wrong to apply the DST change to the RTC itself. Will you be able to know that you already did it once, for example? Changing the clock itself is what my PalmOS PDA does, and certain Redmond-designed operating systems.. it's not good. Unix systems don't do this.
    The smart approach is to always run the RTC at e.g. UTC or whatever, and never change that. Instead you apply DST (and TZ if you run the RTC at UTC) at the application level, typically where you read or display the date. Just look at the date and apply DST if it's after that March Sunday or before the one in October or whenever it is these days. You can never go wrong because there's no risk of doing it twice.

    Then we should all work at getting rid of the whole DST. There's nothing good about it.
  • Tor,

    In my example, I save a bit in EEPROM when the adjustment has been made so it isn't done again, and upon power up I know if DST is in effect. This isn't the only way to do it, but the OP wanted to know how to adjust the RTC.

    Another technique is to save the DST bit in EEPROM and then make the adjustment each time the clock is read. This is a little trickier in that after 23:00 it means also adjusting the day, date and possibly the month, each time the clock is read. But it can be done.

    The best solution I have found is to use a RTC with automatic DST adjustment, like the ISL12022MA which is a very nice chip.

    If your application runs in a place that observes DST, then you're going to have to deal with it one way or another.
  • TorTor Posts: 2,010
    I overlooked that part of the code where you set the bit in the EEPROM. That definitely sorts out one of the problems with changing the actual clock.
    I still think it's infinitely more elegant to simply run the clock at a fixed time setting and apply any adjustments to where the time is used.

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2015-10-05 03:13
    Tor wrote:
    IMO it's wrong to apply the DST change to the RTC itself.
    I agree 100%. The RTC should keep time in GMT. Time-zone and DST corrections should be applied after the fact via software.

  • Thanks
    I'll make that work in my program
  • It's been mentioned that it is better not to change the RTC values. What is the reasoning for this"
  • TorTor Posts: 2,010
    There are several. The most obvious one is that running the RTC on UTC (GMT) makes it possible to get a linearly increasing time from the RTC, with no jumps.

    You would use two functions to get the time: One for getting UTC time (e.g. a function 'gmtime'), and another for getting your local time ('localtime') which would apply your timezone and DST as needed. If you have a filesystem or a datalogger you would timestamp with the UTC time, not the local time. A UTC time stamp can unambiguously be converted to local time, the opposite is not true (the end of DST sets the clock back one hour (typically), thus the same local time could be any of two different UTC time values).

    If you have a program which needs to check how much time has passed you will always want to compare UTC time values, not local time, because during DST changes the latter will jump. You would have to be aware of the DST dates in any program which tries to measure time intervals (and you would have the ambiguous hour-of-change at end of DST to clash with too - and that can't be resolved).

    With the RTC running on UTC you can even move your gadget to another time zone while it's running, apply a TZ (timezone) change, and any program checking for time intervals which you kept running while moving will work fine, because the clock just ticks linearly ahead.
  • An RTC running UTC is simple to maintain and I agree that a UTC time stamp for files makes good sense (especially in an internet connect world).

    Converting the UTC hour to local/DST time is quite simple but the inconvenience of using UTC comes in having to convert the date back one day during the first few hours of each day (i.e. the first four or five hours on the east coast of the US). The code gets a bit messy with each month having a different number of days (no slick metric system yet for days, months and leap years).

    Since I am using my RTC for "human time" I run my RTC set to local time. Below is a routine I added to the S35390A_RTCEngine.spin code that adjusts the RTC's time into and out of daylight saving according to the latest DST rules.

    At this point I run this routine as part of the clock's read time/date routine. The DST flag is stored in the "user register" so stays within the RTC itself. This isn't much of a burden for me since I'm not running my code for speed. If speed is a factor then one could think about using one of the Sieko's alarms to go off each day at 2 AM and seeing that event would trigger a once daily check on the DST rule.

    I originally write this code for a DS1307 RTC where the days of the week ran from 0 to 6 and I arbitrarily assigned Sunday as 0. If I recall correctly this original Seiko code used 1-7 for the days of the week. So in order to utilize this DST code I needed to modify the days of the week to use 0-6 (I think the internals of the Seiko run days of the week from 0 to 6 and the conversion to 1-7 was only in the spin code). A bit of fiddling with this algorithm would get it to work with days of the week using 1-7.

    PUB CheckDST |  hh24
    This routine checks the current date and time to see if an adjustment is necessary into or out of Daylight Savings Time.
    The RTC's DST flag is stored in its free register.
    The rules for DST changed in 2007 for the first time in more than 20 years. The new changes were enacted
    by the Energy Policy Act of 2005, which extended the length of DST in the interest of reducing energy
    consumption. The new rules increased the duration of DST by about one month. DST will now be in effect
    for 238 days, or about 65% of the year, although Congress retained the right to revert to the prior law
    should the change prove unpopular or if energy savings are not significant.
    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
      CASE ClockMonth
        4..10 : DST := +1  'If the RTC month is between April (4) and October (10) then it is currently DST 
        1..2  : DST := 0   'If the RTC month is between December (12) and February (2) then it is not DST  
        3  :               'DST begins at 2:00 AM on the second Sunday of March (3)
          IF ( ClockDate - ClockDay ) =>8  'If the date (1-31) minus the day of the week (0-6) is 8 or more then
            DST := +1                      'we are past the first Sunday so DST is in effect.
            DST := 0
        11 :               'DST ends at 2:00 a.m. on the first Sunday of November
          IF ( ClockDate - ClockDay  ) =<0 'If the date (1-31) minus the day of the week (0-6) is less than 0 then 
            DST := +1                      'DST is still in effect. 
            DST := 0
    ' If the value of DST matches the free register value then no change is needed so just return.
      IF readDSTRegister == DST
        RETURN DST
    ' They do not agree so we are on the first day of the DST change.
    ' Chect to see if we are at 2 AM or later before we make the change, if not just return.
      hh24 := ClockHour
      IF hh24 < 2
        IF DST == 1
          RETURN 0
          RETURN 1
    'We are at or past 2 AM so make the change accordingly
      IF DST == 1
        hh24 := hh24 + 1  'DST now in effect so add 1 to the hour ("spring ahead").
        hh24 := hh24 - 1  'DST is not in effect so substract 1 from the hour ("fall back")
      writeTime( time[0], time[1], hh24, time[3], time[4], time[5], ClockYear )
    ' Update the DST register on the RTC to reflect this change (on subsequent passes through this routine the DST will match this new
    ' resister value and no RTC time change will be made until the next DST date and time event occurs).
      writeDSTRegister( DST )
  • jmgjmg Posts: 15,132
    Sapphire wrote: »
    The best solution I have found is to use a RTC with automatic DST adjustment, like the ISL12022MA which is a very nice chip.

    Interesting part - it is not clear how the DST manages, ie does the part need to be running and 'cross-over' the set points (just like an alarm) ?
    Given DST applies differently around the world, (even flips phase for southern hemisphere) I think it has to be only a threshold cross design ?

  • jmg,

    The chip needs to be running and cross over the set point for the DST adjustment to happen, but will do so on battery and not just Vdd. If you lose Vdd and you have no battery (or it's dead) then you lose the time, so DST really doesn't matter.

    The ISL part is neat in that you specify when the change occurs, either by month-week-day-hour or month-date-hour. It is truly global. Just set the rules and the chip takes care of the rest. So any changes to the rules, or moving to a locale with different rules, can easily be configured.
  • I share Sapphire's enthusiasm for the ISL12020 (same as the ISL12022 but a DFN package). It's a sophisticated chip. The DST function is not enabled by default, but there is an enable bit as well as a flag bit that will indicate when the correction forward or backward has occurred. I'm in UTC camp mostly and don't generally use the 8 DST registers except as an extension of the battery-backed scratchpad ram.

  • Tracy,

    Yes, plus the IRQ/Fout pin can be used for one-time or repeating alarms, and the chip has readable temperature sensor! Along with 128 bytes of battery backed SRAM.
  • To compare contrast the Dallas/Maxim DS323x with the Intersil ISL1202x... One significant difference in my book is how they handle the power supply and battery backup. The DS parts draw a relatively high Vcc current, over 100µA, and then fall back to the 1 or 2 µA timekeeping level when they switch over to battery backup. They can operate the i2c interface at higher current too off the battery. That is good for POS terminals and such that normally operate from an ample power source. The ISL is better I think for systems that are entirely battery powered. They run from Vcc at around 3.5µA, and the backup battery can be a coin cell delivering 1µA for timekeeping and sram backup only.

    For DST switch, I think I'd use the DST registers if I were doing something like a dedicated clock that would display local parking regulations like we have around here, street sweeping monthly starting at 9am on the second Tuesday.
  • Tracy,

    Another plus for the ISL is that the Vbat can be 5v, where on the DS parts, some are limited to 3.3v. I use supercaps, and just charge them with Vdd through a diode+resistor and don't have to worry about exceeding the Vbat max input.
Sign In or Register to comment.