string llGetTimestamp()
Returns the current
time-and-date (a
timestamp) in the format
YYYY-MM-DDThh:mm:ss.ff..fZ, for example:
2004-08-27T00:56:21.785886Z
The letter Z stands for Zulu, the
military time zone name for
UTC. T is just a separator between date and time.
This format allows exact times and easy
sorting, but is not as suited for comparing time as a libc like
timestamp. Nevertheless, it is still possible. (See below.)
This format is one of the options defined by International Standard ISO 8601 (
summary). It is also used to represent a specific instant in time in the
XML Schema standard's
dateTime data type, which is "inspired" by ISO 8601. As such, this is a format for storing in databases and log files, not display to
users or computation.
To get the number of seconds elapsed since 00:00 hours, Jan 1, 1970, use
llGetUnixTime. This function is better suited to comparing time than
llGetTimeStamp.
The following example shows how hours, minutes, and seconds can be extracted from the timestamp.
//A function that returns a vector in the form of <hours,minutes,seconds> using llGetTimestamp()
// Keknehv Psaltery 06/15/05
vector time() //Returns a vector with the current time in hours, minutes, and seconds
{ //In the format <hours,minutes,seconds>
list timestamp = llParseString2List( llGetTimestamp(), ["T",":","Z"] , [] );
return < llList2Float( timestamp, 1 ),
llList2Float( timestamp, 2 ),
llList2Float( timestamp, 3 ) >;
}
AlexanderDaguerre disagrees with the comment about this being an unsuitable format for comparing time; this is one of the things that this format was intentionally designed to support and is the reason that sorting works. Comparing two llGetTimestamp strings should give you the same results as comparing the two instants in some high precision integer format (higher precision than Unix timestamp format, too). Of course, with that decimal point in there you shouldn't compare two such strings for equality for the same reasons that you should never expect two floating-point values to compare equal. AlexanderDaguerre agrees with Ezhar that this format is pretty hard to use for time difference as opposed to comparison.
Ezhar would like an easy way to tell the time difference between two timestamps, which is very simple in UNIX timestamps but not in this format (at least not using LSL).
I just scraped together a function that might do what you ask Ezhar... there may be a couple bugs with it, namely in dealing with leap-years and varying days in months, but that's because I wrote it in 10 mins. I would fix them, but its 3AM and Im tired :) -Chris
// float secsBetween(string, string):
// A very rough way of getting the difference in seconds
// between two timestamps in the form returned by llGetTimestamp.
// Note that this function currently has two problems:
// 1. No accurate leap-year correction.
// 2. No accurate month-day correction (30 days, 31 days, etc)
// Both are fixable, but Im currently too sleepy :)
// Written by: Christopher Omega
// Date: 9/4/04
float secsBetween(string t1, string t2) {
// Parses the timestamps into a two-element list consisting of
// [date, time] where date is a string in the form "YYYY-MM-DD"
// and time is a string in the form "hh:mm:ssZ" (Note: ss is a float value)
list parsed1 = llParseString2List(t1, ["T"], []);
list parsed2 = llParseString2List(t2, ["T"], []);
// Date1 and Date2 are lists in the form of [year, month, day]
list date1 = llParseString2List(llList2String(parsed1, 0), ["-"], []);
list date2 = llParseString2List(llList2String(parsed2, 0), ["-"], []);
// Time1 and Time2 are lists in the form of [hours, minutes, seconds]
// Taking into account the one-letter "Z" suffix on the end of the time element
// by deleting it.
list time1 = llParseString2List(llDeleteSubString(llList2String(parsed1, 1), -1, -1), [":"], []);
list time2 = llParseString2List(llDeleteSubString(llList2String(parsed2, 1), -1, -1), [":"], []);
// Stamp* lists are in the form [year, month, day, hour, min, sec]
list stamp1 = date1 + time1;
list stamp2 = date2 + time2;
// SECONDS_CONVERSION is a list containing the number of seconds in:
// one year, one month, one day, one hour, one minute and one second,
// respectively.
// TODO: Provide accurate leap-year and month-day-count correction.
// Im assuming 365.25 days in a year and 30 days in a month :(
list SECONDS_CONVERSION = [31557600, 2592000, 86400, 3600, 60, 1];
float diffInSecs = 0;
integer i;
for (i = 0; i < 6; ++i) {
// TODO: See if extracting elements as floats here is a reasonable
// accuracy tradeoff.
// Thought: Perhaps we could multiply the seconds
// value by some power of ten at the beginning of this function
// and simply work with it like you would an integer, since its the only
// floating point value.
float element1 = (float) llList2String(stamp1, i);
float element2 = (float) llList2String(stamp2, i);
float conversionFactor = (float) llList2String(SECONDS_CONVERSION, i);
diffInSecs += llFabs(element1 - element2) * conversionFactor;
}
return diffInSecs;
}
I was researching information on dates here and noticed that the statement below was innacurate. Every 100 years is /NOT/ a leap year, except for every 400 years, which /ARE/ a leap year. See (http://mathforum.org/dr.math/faq/faq.calendar.html) for more information. - RichardSolvang
My bad - Ice
Here's another stab at a timestamp-difference function. It doesnt use any kind of zero reference point, so as long as the two times are close enough to one another, the function should handle them fine. It works like the difference operator, subtracting the second parameter from the first - so if the second timestamp is farther into the future then the first (has a larger time value), then it will return a negative value. It should handle month-days and leap years much better then my previous try, but to do so, the code grew a great number of lines. Be careful though, I havent rigorously tested it. -Chris
// Scroll down...
integer min(integer a, integer b) {
if (a > b)
return b;
return a;
}
integer isLeapYear(integer year) {
return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
}
integer daysInMonth(integer month, integer year) {
if (month < 9) {
if (month != 2) {
// Before September, odd numbered months
// are 31 days long.
if (month % 2 != 0) {
return 31;
} else {
return 30;
}
} else {
// February is the odd man out.
if (isLeapYear(year)) {
return 29;
} else {
return 28;
}
}
} else {
// After August, odd numbered months
// are 30 days long.
if (month % 2 != 0) {
return 30;
} else {
return 31;
}
}
}
// timestampDiff(string, string)
// Written by Christopher Omega 10/21/05
// Returns the difference between the two timestamps
// passed to it, subtracting the second parameter from
// the first.
float timestampDiff(string t1, string t2) {
if (t1 == t2)
return 0;
float diff = 0;
integer year1 = (integer) llGetSubString(t1, 0, 3);
integer year2 = (integer) llGetSubString(t2, 0, 3);
integer i;
if (year1 != year2) {
integer minYear = min(year1, year2);
integer maxYear = year1;
if (minYear == year1)
maxYear = year2;
float secsBetween;
secsBetween += 31536000 * (maxYear - minYear);
for (i = minYear; i < maxYear; ++i) {
if (isLeapYear(i))
secsBetween += 86400; // Add extra day.
}
if (year2 == maxYear)
secsBetween *= -1;
diff += secsBetween;
}
integer month1 = (integer) llGetSubString(t1, 5, 6);
integer month2 = (integer) llGetSubString(t2, 5, 6);
if (month1 != month2) {
integer month1Secs;
for (i = 1; i < month1; ++i) {
// 1 day = 24 hrs * 60 mins * 60 secs
month1Secs += daysInMonth(i, year1);
}
month1Secs *= 86400; // Convert days into secs.
integer month2Secs;
for (i = 1; i < month2; ++i) {
month2Secs += daysInMonth(i, year2);
}
month2Secs *= 86400;
diff += month1Secs - month2Secs;
}
// Whew! Now everything past this point should be clear cut
// conversion directly into seconds.
integer days1 = (integer) llGetSubString(t1, 8, 9);
integer days2 = (integer) llGetSubString(t2, 8, 9);
diff += (days1 - days2) * 86400;
integer hours1 = (integer) llGetSubString(t1, 11, 12);
integer hours2 = (integer) llGetSubString(t2, 11, 12);
diff += (hours1 - hours2) * 3600; //1 hr = 60 mins * 60 secs.
integer minutes1 = (integer) llGetSubString(t1, 14, 15);
integer minutes2 = (integer) llGetSubString(t2, 14, 15);
diff += (minutes1 - minutes2) * 60;
float secs1 = (float) llGetSubString(t1, 17, -2); // Skip last char.
float secs2 = (float) llGetSubString(t2, 17, -2);
diff += secs1 - secs2;
return diff;
}
The scripts at LibraryTimeElapsed use this function to compare points in time with high accuracy.
Functions |
Time |
Timestamp