ezTime icon indicating copy to clipboard operation
ezTime copied to clipboard

timezoned.rop.nl works incorrectly for Asia/Tehran, POSIX-style definition doesn't work either

Open Durobot opened this issue 6 years ago • 4 comments

	setDebug(INFO);
	waitForSync();

	Serial.println("UTC:             " + UTC.dateTime());

        Timezone yourTZ;
	yourTZ.setLocation(F("Asia/Tehran"));
	Serial.print(F("Asia/Tehran:  "));
	Serial.println(yourTZ.dateTime());

The output is:

ezTime debug level set to INFO
Waiting for time sync
Querying pool.ntp.org ... success (round trip 28 ms)
Received time: Wednesday, 08-Apr-20 11:41:51.015 UTC
Time is in sync
UTC:             Wednesday, 08-Apr-2020 11:41:51 UTC
Timezone lookup for: Asia/Tehran ... (round-trip 49 ms)  success.
  Olson: Asia/Tehran
  Posix: 
Asia/Tehran:  Wednesday, 08-Apr-2020 11:41:51

If I set POSIX TZ definition to Tehran's (taken from my Kubuntu 19.10 machine, found in /usr/share/zoneinfo/Asia/Tehran), time is calculated incorrectly (DST not taken into account) -

    Timezone myTZ;
    Serial.println("\n----------------------");
    myTZ.setPosix("<+0330>-3:30<+0430>,J79/24,J263/24");
    Serial.print("Asia/Tehran:   " + myTZ.getPosix());
    Serial.println(" " + myTZ.dateTime());

This code prints out

----------------------
Asia/Tehran:   <+0330>-3:30<+0430>,J79/24,J263/24 Wednesday, 08-Apr-2020 15:21:38 <+0330>

According to https://www.timeanddate.com/worldclock/iran/tehran , curent time in Tehran is 16:21:39 IRDT Wednesday, 8 April 2020

I could be wrong, but to me it looks like ezTime ignores DST rules defined with 'J'. From https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html :

Jn This specifies the Julian day, with n between 1 and 365. February 29 is never counted, even in leap years.

And the reason 'J' is used is probably this:

Iran operates Daylight saving Time between 1 Farvardin (March 21) and the 1 Mehr (September 23) when the time is 4.5 hours ahead of Greenwich Mean Time (GMT+4:30).

(from https://greenwichmeantime.com/time-zone/asia/iran/time-iran/ ) So, the days they switch to/from DST are fixed and can't be expressed with Mm.w.d

Durobot avatar Apr 08 '20 12:04 Durobot

Oh wow... Eh, no, ezTime does not presently support Julian day Daylight Savings rules. So that's a real thing huh? It goes on the list of features to be added. I'm so sorry... (Damn, time has lots of weird exceptions. I was just celebrating that the Moroccans got rid of their "Let's have two DST periods a year!" thing so I didn't have to implement it...)

Would you consider lobbying your government to change this? I'm pretty sure lots of devices / IoT stuff / whatever doesn't do this either. You people must be setting a lot of clocks manually.

ropg avatar Apr 08 '20 12:04 ropg

Well, yeah, except I'm not from Iran, I have just learned about this special case while trying to get Posix TZ strings for all Olsen time zone names out there :) I'm actually on the fence on whether I really need this or not. Most probably not, but i just hate leaving an unsolved problem in my code. So, if I actually happen to implement Julian day number in Posix DST rules, please consider merging.

Durobot avatar Apr 08 '20 19:04 Durobot

I'd be happy to merge... :)

ropg avatar Apr 09 '20 07:04 ropg

I have made the changes I think are necessary for DST start / end expressed in Julian days to work (both Jn and n - not taking and taking leap day into consideration), but I still can't convince myself (1) my changes are sufficient, they cover all cases and (2) I haven't broken anything within ezTime in the process. Tried to do some testing, but I'm not sure I correctly understand things like whether I'm setting current time correctly (if it's supposed to be in UTC or local time), etc.

Quite frankly, I'm stuck. Could you please take a look at my changes as the author of ezTime? Here's the gist containing two modified files, ezTime.h and ezTime.cpp.

Update: just to be clear - my modifications to POSIX TZ string parsing code in Timezone::tzTime() do work, and so does the new function I wrote ( makeJulianDayTime() ) to be called from Timezone::tzTime(). I have tested them with Asia/Tehran TZ string ("<+0330>-3:30<+0430>,J79/24,J263/24"), and it is parsed as intended, and current (+0430) time is calculated correctly by ezTime (checked current time in Tehran here).

The question is - will time be calculated correctly after the next DST transition on 21st of September, 2020, and after the next one, etc.

Durobot avatar Apr 30 '20 09:04 Durobot