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

From Second Life Wiki
Jump to navigation Jump to search
(Create page)
 
(Add version that accepts negatives)
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).
Line 9: Line 13:
     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/0xFFFFFFFC; // 0xFFFFFFFC=-4
     c = (b*20+0xFFFFF676)/7305; // -2442
     c = (b*20 + 0xFFFFF676)/7305; // 0xFFFFF676=-2442
     b += c*0xFFFFFE93 + c/0xFFFFFFFC; // -365, -4
     b += c*0xFFFFFE93 + c/0xFFFFFFFC; // 0xFFFFFE93=-365; 0xFFFFFFFC=-4
    a = b*1000/30601;
    b += a*0xFFFFFFE2 + a*0xFFFFFDA7/1000; // 0xFFFFFFE2=-30; 0xFFFFFDA7=-601
 
    return (list)(0xFFFFED94 + c + (a>13)) // 0xFFFFED94=-4716
          + -~((a + 10)%12)
          + b
          + unix/3600%24
          + unix/60%60
          + unix%60;
}
</lsl>
Size in Mono: 492 bytes.
 
This version also works with negative input:
<lsl>
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 += 0xFFFEAE80*~-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/0xFFFFFFFC; // 0xFFFFFFFC=-4
    c = (b*20+0xFFFFF676)/7305; // 0xFFFFF676=-2442
    b += c*0xFFFFFE93 + c/0xFFFFFFFC; // 0xFFFFFE93=-365; 0xFFFFFFFC=-4
     a = b*1000/30601;
     a = b*1000/30601;
     b += a*0xFFFFFFE2 + a*0xFFFFFDA7/1000; // -30, -601
     b += a*0xFFFFFFE2 + a*0xFFFFFDA7/1000; // 0xFFFFFFE2=-30; 0xFFFFFDA7=-601


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


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

Revision as of 11:22, 14 May 2014

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). <lsl> list UnixToDateTime(integer unix) {

   integer c = unix/86400;
   integer a = (c*4 + 102032)/146097 + 15;
   integer b = c + 2442113 + a + a/0xFFFFFFFC; // 0xFFFFFFFC=-4
   c = (b*20 + 0xFFFFF676)/7305; // 0xFFFFF676=-2442
   b += c*0xFFFFFE93 + c/0xFFFFFFFC; // 0xFFFFFE93=-365; 0xFFFFFFFC=-4
   a = b*1000/30601;
   b += a*0xFFFFFFE2 + a*0xFFFFFDA7/1000; // 0xFFFFFFE2=-30; 0xFFFFFDA7=-601
   return (list)(0xFFFFED94 + c + (a>13)) // 0xFFFFED94=-4716
          + -~((a + 10)%12)
          + b
          + unix/3600%24
          + unix/60%60
          + unix%60;

} </lsl> Size in Mono: 492 bytes.

This version also works with negative input: <lsl> 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 += 0xFFFEAE80*~-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/0xFFFFFFFC; // 0xFFFFFFFC=-4
   c = (b*20+0xFFFFF676)/7305; // 0xFFFFF676=-2442
   b += c*0xFFFFFE93 + c/0xFFFFFFFC; // 0xFFFFFE93=-365; 0xFFFFFFFC=-4
   a = b*1000/30601;
   b += a*0xFFFFFFE2 + a*0xFFFFFDA7/1000; // 0xFFFFFFE2=-30; 0xFFFFFDA7=-601
   return (list)(0xFFFFED94 + c + (a>13)) // 0xFFFFED94=-4716
          + -~((a + 10)%12)
          + b
          + unix/3600%24
          + unix/60%60
          + unix%60;

} </lsl>

Size in Mono: 556 bytes.