lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Javier:

On Tue, Mar 28, 2017 at 12:32 PM, Javier Mr <javiersdevmail@ymail.com> wrote:
> I'm having a little bit of trouble converting dates in UTC to timestamps and back to dates.

This is because os.time() needs table in local time. You do not have a
function to work with the date in UTC.

> I obtain the ITC timestamp as os.time( os.date( "!*t" ) ); back when converting it back to date doesn't matter is I use "!*t" or "*t"; I always get the hour wrong, either one hour less or one hour more.

First, if you do not pass a second argument to date, you are doing it
wrong ( just call os.time() ). Assuming that was a typo ( and you
meant os.time( os.date( "!*t", anyts ) ) what you are doing there is
telling "format anyts as a timestamp and then parse it back as local".
This is what you do to TRY to find the current offset with UTC in your
local zone.

Anyway, timestamps ( the numbers ) are not UTC or local, you do not
need to correct them. They are ( in POSIX systems ) defined as the
number of seconds since the epoch. The time value is the same for all
timezones.

Converting timestamps to dates is easy. To convert dates to timestamps
is where you have a problem. What you can try to do is:

1.- Have a date ( table ) in utc, date_utc - convert it to a local ts,
ts_local - It is erroneous.
2.- Use the ts_local to find the time zone offset - os.date("%z", ts_local)
3.- Parse the timezone and correct ts_local

Or you can write a very small function to build the timestamp using
tz_date. The usual way is to use a couple of tables. I routenly use
this in perl:

my @days_per_month = (0,31,28,31,30,31,30,31,31,30,31,30,31); # NB,
dec=#12 not used
---- Acum days counts the days BEFORE day 1 of the month.
my @acum_days = (0,0);

for(1..12) {
    $acum_days[$_+1]=$acum_days[$_]+$days_per_month[$_];
}

sub ymd2days($$$) {
    my ($y,$m,$d) = @_;
    my $days = $d + $acum_days[$m] + $y * 365 + int($y/4)
-int($y/100)+ int($y/400);
    my $bisiesto = not (  ($y%4) or (not $y%100 and $y%400) );
    --$days if ($bisiesto and $m<3);
    return $days;
}

( leap year in spanish is "año bisiesto" )

use constant EPOCH_DAYS =>  1970 * 365 +
int(1970/4)-int(1970/100)+int(1970/400) +1;

>From this you can turn a date to a timestamp : (
seconds+60*(minutes+60*(hours+24*(ymd2days(y,m,d)-EPOCH_DAYS))))

Porting it to lua is not that difficult and left as an exercise to the
reader ( I can do it if you have troubles, just not now ).

Francisco Olarte.