Search code examples
datetimedatetime-formatmaxima

date and time (local time instead of UTC) (Maxima)


These lines give the date and time in UTC:

t:timedate(absolute_real_time() - (10*3600));
t0:substring(t,1,20);
t1:concat(substring(t,12,17), " ", substring(t,9,11), "/", substring(t,6,8), "/", substring(t,1,5));
t2:concat(substring(t,1,5), substring(t,6,8), substring(t,9,11), substring(t,12,14), substring(t,15,17), substring(t,18,20));

I know that '?\*autoconf\-version\*;' can give the Maxima version number, so maybe there is some undocumented way to get the local time.

Otherwise are there any ready-made functions that can convert UTC time to local time given conditions for start/end of daylight saving time e.g. UTC time to UK time (which is GMT/BST depending on the time of year)?


Solution

  • To clarify the problem, before revealing the solution: these are the steps that I take in Maxima v5.30 to get the time in UTC, in a readable format:

    Note: When I use Maxima v5.30 (in the UK), for some unknown reason, the time is always UTC adjusted by 10 hours, and does not adjust for DST.

    /* 1st Jan 2017 12 noon: */
    timedate(3692260800); /* "2017-01-01 22:00:00+10:00" */
    timedate(3692260800-10*3600); /* "2017-01-01 12:00:00+10:00" */
    substring(timedate(3692260800-10*3600),1,20); /* "2017-01-01 12:00:00" */
    

    Note: timedate works better/differently in later versions of Maxima, but some institutions recommend installing a specific version of Maxima.

    Sometimes I want the date in the form: 'yyyyMMddHHmmss'. A function for this is:

    SecUTCToDate(vSec,vHour):=
    block([d1,d2],
    d1:timedate(vSec+vHour*3600),
    d2:concat(substring(d1,1,5), substring(d1,6,8), substring(d1,9,11), substring(d1,12,14), substring(d1,15,17), substring(d1,18,20)),
    parse_string(d2)
    );
    

    Note: [d1,d2] keeps those variables local to within the block, and not global.

    To get the local time I have to add on hours based on my time zone (0 in the UK), and DST. To calculate whether a time is within the DST period requires an individual function per time zone: in the UK, and many European countries, one such function is:

    /* correct for the years 1900-2200 inclusive */
    SecUTCIsDSTUK(vSec):=
    block([vLeap,vDaysMar25,vDaysOct25,vWDayMar25,vWDayOct25,vRange1,vRange2],
    vYear : parse_string(substring(timedate(vSec),1,5)),
    vLeap : floor((vYear-1900)/4), if (vYear>=2100) then vLeap : vLeap-1,
    vDaysMar25 : (vYear-1900)*365 + vLeap + 83,
    vDaysOct25 : vDaysMar25 + 214,
    vWDayMar25 : mod(vDaysMar25+1,7),
    vWDayOct25 : mod(vDaysOct25+1,7),
    vRange1 : (vDaysMar25+mod(-vWDayMar25,7))*86400 + 3600,
    vRange2 : (vDaysOct25+mod(-vWDayOct25,7))*86400 + 3600,
    if ((vSec >= vRange1) and (vSec < vRange2)) then 1 else 0);
    

    You can create a mac file with such a function, and call up the the function when needed, e.g.:

    load("C:\\MyFolder\\MyFile.mac");
    SecUTCIsDSTUK(absolute_real_time());
    SecUTCIsDSTUK(absolute_real_time()+86400*180);