Difference between revisions of "User:Pedro Oval/UnixToDateTime"

From Second Life Wiki
Jump to navigation Jump to search
(Create page)
 
m (<lsl> tag to <source>)
 
(3 intermediate revisions by one other user not shown)
Line 1: Line 1:
Convert a Unix timestamp (e.g. as obtained by [[llGetUnixTime]]) to a UTC date and time.
Convert a Unix timestamp (e.g. as obtained by [[llGetUnixTime]]) to a UTC date and time.
Adapted and optimized from this Ruby version: http://ptspts.blogspot.com/2009/11/how-to-convert-unix-timestamp-to-civil.html
Optimized for size in Mono.


Returns a list with the format <code>[year, month, day, hours, minutes, seconds]</code> (UTC).
Returns a list with the format <code>[year, month, day, hours, minutes, seconds]</code> (UTC).


This is the shortest version, but it works with positive input only (i.e. with numbers representing dates from 1970 to 2037).
This is the shortest version, but it works with positive input only (i.e. with numbers representing dates from 1970 to 2037).
<lsl>
<source lang="lsl2">
list UnixToDateTime(integer unix)
list UnixToDateTime(integer unix)
{
{
     integer c = unix/86400;
     integer c = unix/86400;
     integer a = (c*4 + 102032)/146097 + 15;
     integer a = (c*4 + 102032)/146097 + 15;
     integer b = c + 2442113 + a + a/0xFFFFFFFC; // -4
     integer b = c + 2442113 + a + a/(integer)-4;
     c = (b*20+0xFFFFF676)/7305; // -2442
     c = (b*20 + (integer)-2442)/7305;
     b += c*0xFFFFFE93 + c/0xFFFFFFFC; // -365, -4
     b += c*(integer)-365 + c/(integer)-4;
     a = b*1000/30601;
     a = b*1000/30601;
     b += a*0xFFFFFFE2 + a*0xFFFFFDA7/1000; // -30, -601
     b += a*(integer)-30 + a*(integer)-601/1000;


     return (list)(0xFFFFED94+c+(a>13)) + -~((a+10)%12) + b + unix/3600%24 + unix/60%60 + unix%60; // -4716
     return (list)((integer)-4716 + c + (a>13))
          + -~((a + 10)%12)
          + b
          + unix/3600%24
          + unix/60%60
          + unix%60;
}
}
</lsl>
</source>
Optimized for Mono. Size in Mono: 492 bytes.
Size in Mono: 492 bytes.
 
This version also works with negative input:
<source lang="lsl2">
list UnixToDateTime(integer unix)
{
    integer c = unix/86400;


Adapted and optimized from this Ruby version: http://ptspts.blogspot.com/2009/11/how-to-convert-unix-timestamp-to-civil.html
    // LSL doesn't do floor division as required here, so we have to fix up the result
    if (unix & 0x80000000)
    {
        unix += (integer)-86400*~-c; // we're interested in unix mod 86400 from here on,
                                // but mod doesn't work well with negatives either
        if (unix^86400) --c;    // c needs fixup unless unix%86400 == 0
    }
 
    integer a = (c*4 + 102032)/146097 + 15;
    integer b = c + 2442113 + a + a/(integer)-4;
    c = (b*20 + (integer)-2442)/7305;
    b += c*(integer)-365 + c/(integer)-4;
    a = b*1000/30601;
    b += a*(integer)-30 + a*(integer)-601/1000;
 
    return (list)((integer)-4716 + c + (a>13))
          + -~((a + 10)%12)
          + b
          + unix/3600%24
          + unix/60%60
          + unix%60;
}
</source>
 
Size in Mono: 556 bytes.
 
[[Category:LSL User-Defined Functions]]

Latest revision as of 15:31, 22 January 2015

Convert a Unix timestamp (e.g. as obtained by llGetUnixTime) to a UTC date and time.

Adapted and optimized from this Ruby version: http://ptspts.blogspot.com/2009/11/how-to-convert-unix-timestamp-to-civil.html

Optimized for size in Mono.

Returns a list with the format [year, month, day, hours, minutes, seconds] (UTC).

This is the shortest version, but it works with positive input only (i.e. with numbers representing dates from 1970 to 2037).

list UnixToDateTime(integer unix)
{
    integer c = unix/86400;
    integer a = (c*4 + 102032)/146097 + 15;
    integer b = c + 2442113 + a + a/(integer)-4;
    c = (b*20 + (integer)-2442)/7305;
    b += c*(integer)-365 + c/(integer)-4;
    a = b*1000/30601;
    b += a*(integer)-30 + a*(integer)-601/1000;

    return (list)((integer)-4716 + c + (a>13))
           + -~((a + 10)%12)
           + b
           + unix/3600%24
           + unix/60%60
           + unix%60;
}

Size in Mono: 492 bytes.

This version also works with negative input:

list UnixToDateTime(integer unix)
{
    integer c = unix/86400;

    // LSL doesn't do floor division as required here, so we have to fix up the result
    if (unix & 0x80000000)
    {
        unix += (integer)-86400*~-c; // we're interested in unix mod 86400 from here on,
                                // but mod doesn't work well with negatives either
        if (unix^86400) --c;    // c needs fixup unless unix%86400 == 0
    }

    integer a = (c*4 + 102032)/146097 + 15;
    integer b = c + 2442113 + a + a/(integer)-4;
    c = (b*20 + (integer)-2442)/7305;
    b += c*(integer)-365 + c/(integer)-4;
    a = b*1000/30601;
    b += a*(integer)-30 + a*(integer)-601/1000;

    return (list)((integer)-4716 + c + (a>13))
           + -~((a + 10)%12)
           + b
           + unix/3600%24
           + unix/60%60
           + unix%60;
}

Size in Mono: 556 bytes.