Timezone

I would like to get a little clarification on the startup ‘timezone’ for those of us in areas where we have daylight savings changes. I’m in the Pacific timezone which is GMT-8 in the winter (standard time) and GMT-7 in the summer (daylight time). What value should the timezone be in Lua startup code? I think it should be ‘-8’ and that the code should handle the daylight savings adjustment, correct?

Also, just curious, why does OpenLuup need this at all? Is it not possible to get this from the OS that OpenLuup is running on? Seems like the OS should handle this and OpenLuup should follow along. But maybe OpenLuup can’t get the timezone in all cases?

Many places do have ‘daylight savings time’ and the system should cope with that transparently, if configured correctly. The timezone is, somewhat, a separate issue.

In fact, the ‘timezone’ top-level system parameter is not used at all by openLuup, although it may be used by any plugin or Lua code (although, I doubt that it is.) So setting it to any value should have absolutely no effect. I really should get openLuup to set it - I’ll look at doing that in the next release; it would be nice if it was correct. It’s there because it’s there on Vera, and once upon a time, I didn’t know if it was going to be relevant. So that answers your second question.

However…

… openLuup calculates sunrise and sunset times itself, relying both on system time and luup.latitude and luup.longitude to be correct. Not only must the system time be correct, but the locale should be set correctly, in order for the timezone offset (and, indeed, DST) to be known.

The time calculations are slightly difficult to check for me, since my development system is based on UK time which is, fundamentally, the same as UTC. I should perhaps set up a test system for another time zone, but not having done that, there is a remote possibility that I have made a mistake (earlier version did have a DST error which some kind user put me right on.)

Would I be right in thinking that this code produces the correct timezone shift (independent of DST) ?

local utc  = os.time()
local zone = os.date "*t"
local diff = os.difftime (os.time (zone), utc) / 3600

print (diff)

If you want to know the timezone I think you want this:

local now = os.time() local utcdate = os.date("!*t", now) local localdate = os.date("*t", now) local diff = os.difftime(os.time(localdate), os.time(utcdate))/3600 print("diff is " .. diff) return true

I’m in Pacific which is GMT-8. The above will return ‘-8’ even though my zone is currently in daylight savings. So even though the wall clock time is currently 7 hours different from GMT, the above gives the -8. And next week, when DST ends, this should still give -8. (I don’t know that the function os.difftime is needed - if os.time() returns integers, seems like we could just subtract them.)

Note that not all zones are integers. India uses IST which is GMT+5:30.

Can you explain to me why you think:

local now = os.time()
local utcdate   = os.date("!*t", now)
local utc = os.time (utcdate)

is different from:

local utc = os.time()

… ???

Since, AFAIK, os.time() is always in UTC?

I don’t believe that what you wrote is different. But I do believe we need to use the same point in time as the reference, i.e., “now”, for the subtraction. Perhaps that is better described as “PointInTime” and not “now”. So we get the reference point in time (“now”), format it both in the local HMS and the UTC HMS, convert back to seconds in UTC, and subtract.

I picked this up from: lua-users wiki: Time Zone and I tested it on my local system.

By the way, I don’t think that initial os.time() call is even needed. As long as the comparison is done with the same input, it should work. I think it is best to use the current time as the timezone definition could have changed somehow since 1970 so leave that to the OS to figure out. I tried this and it gave the same ‘-8’ correct result:

local now = 1000000 local utcdate = os.date("!*t", now) local localdate = os.date("*t", now) local diff = os.difftime(os.time(localdate), os.time(utcdate))/3600 print("diff is " .. diff)

Yes indeed, as should the value zero, so you wouldn’t have to do the diff either.

I think you need the diff. If you run that code on my system it does say ‘-8’ for the output. How else would you get that diff? I must misunderstand what you are saying?

Here’s the way I think of think of it: the *t version takes the wall clock time and converts it into the UTC seconds given the current timezone. The !*t takes that very same wall clock time and converts into UTC seconds with no timezone (plain UTC). They will be different (unless your timezone is 0).

And I’m not sure I could use the value 0, because my timezone is -8 - that would make the os.time go negative which is probably (?) not allowed. When I get a chance I’ll try running os.time on a negative number. But I think that’s moot - using a call to os.time() initially is probably safest.

What does this give?

local diff = os.time(os.date("*t", 0)) / 3600
print("diff is " .. diff)

“diff is 0”

This, however, gives “diff is 8”

local diff = os.time(os.date("!*t", 0)) / 3600 print("diff is " .. diff)
As long as the timezone is static (it should be) this seems like it would work for west of GMT. What about the case with negative offsets? If you are east of GMT, then this asks os.date to return a value before Jan 1, 1970, 00:00. And relies os.time allowing negative numbers since it would be before then. Is that guaranteed by these calls?

@akbooer, it would seem Vera does not use the ?timezone’ attribute but rather the ‘gmt_offset’ one… this seems to be confirmed by MCV in http://forum.micasaverde.com/index.php/topic,10276.msg70562.html#msg70562
And indeed my Vera shows a gmt_offset of 1 consistent with my timezone (France) and a timezone attribute of 0… however my openLuup system shows 0 and 1 respectively ???
So whatever calculation method you settle for, it is the gmt_offset attribute that should be updated for full Vera compability IMHO.

I’ve put the following function into the openLuup.timers module:

local function gmt_offset ()
  local now = os.time()
  local localdate = os.date("*t", now)
  return os.difftime(os.time(localdate), now) / 3600
end

which is used to set the gmt_offset system attribute at startup.

This will appear in the next GitHub commit.

Many thanks @logread and @jswim788.

I believe you need the ‘!’ to make this work. The function you list returns 0 in GMT-8 zone. Also, I think you need to reverse the diff to get the polarity correct. How about this?

local function gmt_offset () local now = os.time() local localdate = os.date("!*t", now) return os.difftime(now, os.time(localdate)) / 3600 end

You’re right, I’ve screwed it up (again.)