Time.local() difference?

Hi all

I’m a bit confused about the new Time.local() function.
I understand via the docs that it is meant to display time affected by the timezone setting. However I thought time.now always did this anyway?

The way I have been using it is this:

Set timezone - I’m in NZ, UTC+12 so:

Time.zone(12);

Then:

long timeStore = Time.now();
uint8_t hour = Time.hour(timeStore);
uint8_t min = Time.minute(timeStore);

This gives me the correct time in 24hr format (I adjust DST separately).
So, what am I missing with time.local()? From my experience, time.now() seems to do everything time.local() says it does?

Time.hour() and Time.minute() do take time zone into account, and that is what you’re looking at. Try printing Time.now() and Time.Local() and see what you get. Passing the current time to Time.hour() is the same as calling it with no argument.

1 Like

Thanks @Ric I actually didn’t realise you could call Time.hour() and Time.minute() without an argument :smile:
Perhaps it used to be like this in an older version of firmware…

Nope, this was right there from the beginning :wink:

But the Time.now()/Time.local() functions return the lower level timestamp which can be used for time calculations much easier than hour:minute:second notation.
And since now() does not contain the zone info local() was added.

1 Like

ressurecting thi thread, perhaps mine is a firmware version issue…

At the moment UTC is 15:07

I’m using this:

void setup() {
  Particle.variable("time", currentTime);
  Particle.variable("UTC", utc);
  Particle.variable("LOCAL", local);

  Time.zone(-5);
}

void loop()
{
  utc = Time.hour(Time.now());
  local = Time.hour(Time.local());
  sprintf(currentTime, "%02d:%02d", Time.hour(), Time.minute());

and yet it seems that now() , which I expect to return UTC time, unaffected by zone() is somehow being affected:

FYI I am using DST thus the 4 hour difference…

0.6.2 on Photon

Time.hour() is always affected by the provided zone not Time.now().
In other words, Time.hour() will always give you the localised hour of the time you pass in.
What does Time.hour() without any parameter give you?

correct local time.

That seems wrong… but maybe it is the docs that are not clear:

hour()
Retrieve the hour for the current or given time. Integer is returned without a leading zero.
// Print the hour for the current time
Serial.print(Time.hour());

// Print the hour for the given time, in this case: 4
Serial.print(Time.hour(1400647897));Optional parameters: Integer (Unix timestamp)Returns: Integer 0-23

if now() returns UTC timestamp then hour() should, it seems to me, passing the function a UTC timestamp should return the hour of that timestamp regardless of local time.

So if the docs are lying (a lie of omission) then how do I simply get hour() for current UTC? i.e. pseudo:

utcHour = Time.hour(Time.now());

This is what’s actually happening
When you pass a time to these functions, the provided time will be adapted by these two functions

#define localtime(tt) gmtime(tt)
 
int TimeClass::hour(time_t t)
{
	Refresh_UnixTime_Cache(t);
	return calendar_time_cache.tm_hour;
}

static struct tm Convert_UnixTime_To_CalendarTime(time_t unix_time)
{
	struct tm *calendar_time;
	calendar_time = localtime(&unix_time);
	calendar_time->tm_year += 1900;
	return *calendar_time;
}

static void Refresh_UnixTime_Cache(time_t unix_time)
{
    unix_time += time_zone_cache;
    unix_time += dst_current_cache;
    if(unix_time != unix_time_cache)
    {
            calendar_time_cache = Convert_UnixTime_To_CalendarTime(unix_time);
            unix_time_cache = unix_time;
    }
}

The confusing problem here is the double meaning of “given time”.
Since the time you pass in does not carry a flag whether it is UTC of local the function cannot distinguish which it is.
But with your (somewhat valid) interpretation of “given time” and “hour for” that time one could expect that Time.hour(Time.local()) and Time.hour(Time.now()) should actually return the same number - after all the it it’s 3:00 UTC the UTC hour should be 3 and with the local time 3:00 local time should be the same thing - but with the code above that’s just not possible, since only an arbitrary number is passed in that does not tell whether it’s local or UTC.

So the (unspoken) convention is applied, that times that go in are considered UTC and times that come out will be localised.

I agree, that (unspoken) part may pose a problem as it already and repeatedly led to confusion in connection with Time.format(Time.local()).

thanks, I appreciate the full enchilada explanation.

at the end of the day I can get the current UTC offset (ergo UTC hour) with this kind of workaround:

currentOffset = (Time.local() - Time.now()) / 3600;

'cuz there doesn’t seem to be a getter in the time library. I’m working on code that doesn’t set the offset, pero it needs to know nonetheless.

1 Like

Unless you’re in French Polynesia (-0930), Labrador & Newfoundland (-0330), Iran (+0330), Afghanistan (+0430), India & Sri Lanka (+0530), Nepal (+0545), Cocos Islands & Myanmar (+0630), Western Australia (+0845), Australia (+0930), New South Wales (+1030), Chatham Islands (+1245) :slight_smile:

i guess

1 Like

I have just filed an issue to allow for more flexibility

Slight corrections:
Western Australia (+0845) - This is “Australian Central Western Standard Time”. It applies to a very small part of WA & SA and is not official. WA uses Australian Western Standard Time which is +8
Australia (+0930) - You mean Central Australia (SA and NT)
New South Wales (+1030) - NSW is AEST which is +10. +10:30 is Lord Howe Island only.

Back on topic, could we please get the documentation updated to clarify the behaviour of the Time functions? I’ve seen this misunderstanding come up many times.