Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find out timezone offset

I wish to find the timezone offset using Lua, however I'm facing what looks odd behaviour, so I must be missing something.

I'm using the code:

local t1 = os.time();
local t2 = os.time( os.date( "!*t" ) );
print( t1, t2, t1 - t2 );

local t1 = os.time( os.date( "*t" ) );
local t2 = os.time( os.date( "!*t" ) );
print( t1, t2, t1 - t2 );

local t1 = os.date( "%c" );
local t2 = os.date( "!%c" );
print( t1, t2 );

local t1 = os.time( os.date( "*t", 86400 ) );
local t2 = os.time( os.date( "!*t", 86400 ) );
print( t1, t2, t1 - t2 );

local t1 = os.date( "*t" );
local t2 = os.date( "!*t" );
print( t1.hour, t1.isdst, t2.hour, t2.isdst );
print( ((t1.hour - t2.hour) * 60 + (t1.min - t2.min)) * 60 );

Which produces the output:

1496733916      1496730316      3600
1496733916      1496730316      3600
06/06/17 09:25:16       06/06/17 07:25:16
86400   82800   3600
9       true    7       false
7200

Now I'm located in UTC+2 (currently due to summer time, in winter is UTC+1, CEST) so I expected to see an offset of 7200 seconds. However the first two attempts, which should be equivalent, and they are; give me a difference of only one hour. When printing the time in human readable format it can clearly be seen that the offset between both are 2 hours. The fourth attempt is using a fixed point in time (86400 number of seconds in a day, technique from this question) the offset is also 1 hour). Finally when directly subtracting directly the hours (and minutes just in case of not whole hours offset) I get the 2 hours offset.

I suspect this is due to the daylight saving time or dst. What I'm trying to accomplish is get the time from a timestamp (already in UTC), and since os.time is in local time I need to convert that timestamp so it matches localtime.

Or am I completely missing something?

like image 573
Javier Mr Avatar asked Jun 06 '17 07:06

Javier Mr


People also ask

How do you find time zone offset?

getTimezoneOffset() returns the difference between UTC time and local time. getTimezoneOffset() returns the difference in minutes. For example, if your time zone is GMT+2, -120 will be returned.

How do I find my UTC offset?

This difference is expressed with respect to UTC and is generally shown in the format ±[hh]:[mm], ±[hh][mm], or ±[hh]. So if the time being described is two hours ahead of UTC (such as in Kigali, Rwanda [approx. 30° E]), the UTC offset would be "+02:00", "+0200", or simply "+02".

What is offset in time zone?

What is a "zone offset"? A zone offset is the difference in hours and minutes between a particular time zone and UTC. In ISO 8601, the particular zone offset can be indicated in a date or time value. The zone offset can be Z for UTC or it can be a value "+" or "-" from UTC.

How do I find user timezone?

The client's timezone offset could be detected by using the Date object's getTimezoneOffset() method. The getTimezoneOffset() method returns the time difference between UTC time and local time, that is the time offset, in minutes.


1 Answers

As stated in the manual, you shouldn't use the result of os.time() directly, because it can be any value. Use os.date() to get some meaningful information out of it.

It only has any known meaning at all in a few systems, and even then it's only defined that it's a number of seconds since some date.

That being said, the reason you're having this problem seems to be the fact that your table has an isdst flag set. This means os.time() will automatically subtract an hour from it, so you're back to winter time.

Your last aproach is bugged too, by the way, since it won't work in the hours before midnight, where one timestamp is already in the next day, so the difference of the hour fields doesn't work anymore.

The correct way of doing this is surprisingly easy:

local timezone = os.date('%z') -- "+0200"
local signum, hours, minutes = timezone:match '([+-])(%d%d)(%d%d)'

print(signum, hours, minutes)

local dt = (tonumber(signum..hours)*3600 + tonumber(signum..minutes)*60)

print(dt, type(dt))

Which prints:

+     02    00
7200  number
like image 116
DarkWiiPlayer Avatar answered Sep 27 '22 23:09

DarkWiiPlayer