ezTime icon indicating copy to clipboard operation
ezTime copied to clipboard

Timezone not applying to makeTime

Open chinswain opened this issue 5 years ago • 4 comments

Is this expected behavior? I'm sure I'm doing something silly but If I set up a time_t element it prints without timezone adjustment.

The default timezone works, deconstructing t shows the hour as 21 and the epoch time is correct.

#include <ezTime.h>
#include <WiFi.h>
Timezone myTZ;

void setup() {
  Serial.begin(115200);
  WiFi.begin("", "");
  waitForSync();

  myTZ.setLocation(F("gb"));
  myTZ.setDefault();
  Serial.print("TimeZone: "); Serial.println(dateTime());
  Serial.print("epoch myTZ : "); Serial.println(myTZ.now());
  
  time_t t = 0;
  t = makeTime(21, 45, 00, myTZ.day() , myTZ.month(), myTZ.year());
  Serial.print("Test: "); Serial.println(myTZ.dateTime(t));

  Serial.print("epoch Test : "); Serial.println(t);

  tmElements_t tmTest;
  breakTime(t, tmTest);
  Serial.print("Hour: "); Serial.println(tmTest.Hour);
}

void loop() {

}
TimeZone: Friday, 26-Oct-2018 21:45:27 BST
epoch myTZ : 1540590327

Test: Friday, 26-Oct-2018 20:45:00 BST
epoch Test : 1540590300

Hour: 21

chinswain avatar Oct 26 '18 21:10 chinswain

makeTime is timezone-agnostic on purpose: it just converts between two ways of writing time. So yes, it would represent in UTC. Not sure what the bigger-picture things is you are trying to accomplish, but you can use tzTime to convert epoch seconds in one timezone to another.

ropg avatar Oct 27 '18 11:10 ropg

@ropg

you can use tzTime to convert epoch seconds in one timezone to another.

But that isn't the way time_t values are supposed to work. A time_t value denotes a specific point in time by specifying an elapsed amount of time since a single point in time known as the Epoch. There is only a single Epoch. The Epoch is not a specific datetime within a timezone. A time_t value does not depend on or is not modified by the timezone or any local time conversion rules. A time_t does not represent an elapsed time from some point in time based on a local timezone. A time_t represents the number of seconds since Jan 1, 1970 00:00:00 UTC (not counting leap seconds) i.e. there is no such thing as a local time time_t value (These types of munged/modified local time time_t values can be useful under the hood internal to the library but should never be exposed back up to the application)

At any given point in time, the time_t value returned to the application is same value in EVERY timezone on the planet.

It has to work this way to be able to do timestamping and to be able to easily convert individual time_t values to local datetimes and broken down values.

I wrote about this some more in this Arduino thread: https://forum.arduino.cc/index.php?topic=568903.0

I'll soon be creating another issue about time_t values not being handled properly and a recommendation with more details of how to fix it. The summary is that all time_t values should represent an offset from the single Unix epoch. (this is how they work on unix/linux) To make that happen:

  • all now() functions must return the same time_t value from the Unix epoch.
  • All functions that receive a time_t argument must accept a proper Unix epoch time_t value
  • makeTime() moves to the Timezone class so it can convert from local time fields to a Unix epoch time_t
  • breakTime() moves to the Timezone class to do the reverse of makeTime()
  • compileTime() must return a tmElements or be moved to the TimeZone class since there is no way to create a proper time_t value from the compiler provided local date/time info without having timezone information.

Once this is done, there is no longer a need to specify UTC vs LOCAL since proper Unix time_t values are always from the Unix Epoch and all functions will be using/returning time_t values from the same single epoch.

For most users, correcting the code to use proper Unix time_t values will be completely transparent.

bperrybap avatar Jan 22 '19 06:01 bperrybap

I guess when I wrote this I wanted to make it a replacement for Arduino Time library that didn't have timezones, and I didn't want to break code that uses makeTime() and breakTime() by producing unexpected answers to code that isn't timezone-aware.

But I see your point. I've reopened the issue, and as soon as I get some time to sit down with ezTime (early March?), I'll probably implement it the way you suggest. Might come back to you to bounce ideas back and forth at that time, if I may.

ropg avatar Jan 22 '19 08:01 ropg

Sounds good. Look forward to working with you on this. Funny about the Time/TimeLib library not supporting timezones. I kidded Michael (The original author) about it. It wasn't a priority for him since he lived in London which doesn't need any offset from UTC.

I think it is possible to provide compatibility with existing TimeLib sketch code and use proper time_t values by having both ezt and TimeZone makeTime() and breakTime().

What will be difficult will be to maintain compatibility with the current ezTime API behavior. But if that is important, it is probably possible with some additional constructor parameters that set flags/states/modes in the Timezone object. But we can dig into it further, when you are ready.

bperrybap avatar Jan 22 '19 08:01 bperrybap