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

From Second Life Wiki
Jump to navigation Jump to search
m (Add category, fix sum spacing)
m (<lsl> tag to <source>)
 
(One intermediate revision by one other user not shown)
Line 8: Line 8:


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; // 0xFFFFFFFC=-4
     integer b = c + 2442113 + a + a/(integer)-4;
     c = (b*20 + 0xFFFFF676)/7305; // 0xFFFFF676=-2442
     c = (b*20 + (integer)-2442)/7305;
     b += c*0xFFFFFE93 + c/0xFFFFFFFC; // 0xFFFFFE93=-365; 0xFFFFFFFC=-4
     b += c*(integer)-365 + c/(integer)-4;
     a = b*1000/30601;
     a = b*1000/30601;
     b += a*0xFFFFFFE2 + a*0xFFFFFDA7/1000; // 0xFFFFFFE2=-30; 0xFFFFFDA7=-601
     b += a*(integer)-30 + a*(integer)-601/1000;


     return (list)(0xFFFFED94 + c + (a>13)) // 0xFFFFED94=-4716
     return (list)((integer)-4716 + c + (a>13))
           + -~((a + 10)%12)
           + -~((a + 10)%12)
           + b
           + b
Line 26: Line 26:
           + unix%60;
           + unix%60;
}
}
</lsl>
</source>
Size in Mono: 492 bytes.
Size in Mono: 492 bytes.


This version also works with negative input:
This version also works with negative input:
<lsl>
<source lang="lsl2">
list UnixToDateTime(integer unix)
list UnixToDateTime(integer unix)
{
{
Line 38: Line 38:
     if (unix & 0x80000000)
     if (unix & 0x80000000)
     {
     {
         unix += 0xFFFEAE80*~-c; // we're interested in unix mod 86400 from here on,
         unix += (integer)-86400*~-c; // we're interested in unix mod 86400 from here on,
                                 // but mod doesn't work well with negatives either
                                 // but mod doesn't work well with negatives either
         if (unix^86400) --c;    // c needs fixup unless unix%86400 == 0
         if (unix^86400) --c;    // c needs fixup unless unix%86400 == 0
Line 44: Line 44:


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


     return (list)(0xFFFFED94 + c + (a>13)) // 0xFFFFED94=-4716
     return (list)((integer)-4716 + c + (a>13))
           + -~((a + 10)%12)
           + -~((a + 10)%12)
           + b
           + b
Line 57: Line 57:
           + unix%60;
           + unix%60;
}
}
</lsl>
</source>


Size in Mono: 556 bytes.
Size in Mono: 556 bytes.


[[Category:LSL User-Defined Functions]]
[[Category:LSL User-Defined Functions]]

Latest revision as of 14: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.