diff --git a/lib/modules/Calendar.pmod/module.pmod b/lib/modules/Calendar.pmod/module.pmod index 2b2fada6921170c215bc2ec424e8b4599c0e0a8b..b87f1b3041a487a09c6b87e57e108a8d5aace6a2 100644 --- a/lib/modules/Calendar.pmod/module.pmod +++ b/lib/modules/Calendar.pmod/module.pmod @@ -114,3 +114,121 @@ class _TimeUnit object next() { return this+1; } object prev() { return this+(-1); } } + + + + +//! +//! function datetime(int|void unix_time) +//! Replacement for localtime. +//! +//! function datetime_name(int|void unix_time) +//! Replacement for ctime. +//! +//! function datetime_short_name(int|void unix_time) +//! Replacement for ctime. +//! + +// +// Maybe these auxiliary routines should be somewhere else? Maybe even +// written in C? +// +// +static private int ymd2jd(int y, int m, int d) +{ + if(m<3) { + y--; + m+=12; + } + return 1720995+d+2- (y/100) + (y/400) + (36525*y)/100 + (306001*(m+1))/10000; +} + +static private int y2jd(int y) +{ + y--; + return 1721426 - (y/100) + (y/400) + (36525*y)/100; +} + +static private int leapyear(int year) +{ + if((year%400) == 0) + return 1; + if((year%100) == 0) + return 0; + if((year%4) == 0) + return 1; + return 0; +} + +static private int week(int year, int month, int day) +{ + int delta_day, first_time, yday, first_day, first_next_day; + + first_time = y2jd(year); + yday = ymd2jd(year, month, day)-first_time; + first_day = first_time%7; + first_next_day = y2jd(year+1)%7; + + if((yday > (364+leapyear(year)-first_next_day)) && + (first_next_day <= 3)) + return 1; + + if(first_day <= 3) { + /* Week begins on Thursday or erlier, means week one here. */ + delta_day = first_day; + } else { + /* Week begins on Friday or later, means same week as last year. */ + if(yday + first_day <= 6) { + /* Return the last week previous year. */ + return week(year-1, 12, 28); + } + delta_day = first_day-7; + } + + /* Calculate week. Begin with week 1. */ + return (yday + delta_day)/7 + 1; +} + +// Sane replacement for localtime(). +mapping(string:int) datetime(int|void unix_time) +{ + mapping t = localtime(unix_time || time()); + return ([ "year":t->year+1900, + "month":t->mon+1, + "day":t->mday, + "hour":t->hour, + "minute":t->min, + "second":t->sec, + "week":week(t->year+1900, t->mon+1, t->mday), + // ISO weekdays begin with Monday as 1 --- Sunday as 7. + "weekday":((t->wday+6)%7)+1, + "yearday":t->yday, + "timezone":t->timezone, + // Dayligt-saving time. + "DST":t->isdst ]); +} + +// Sane replacement for ctime(). +string datetime_name(int|void unix_time) +{ + array(string) day_names = ({ "Mon", "Tue", "Wed", "Thu", + "Fri", "Sat", "Sun" }); + array(string) month_names = ({ "Jan", "Feb", "Mar", "Apr", + "May", "Jun", "Jul", "Aug", + "Sep", "Oct", "Nov", "Dec" }); + + mapping t = datetime(unix_time); + return sprintf("%04d-%02d-%02d (%s) -W%02d-%d (%s) %02d:%02d:%02d", + t->year, t->month, t->day, month_names[t->month-1], + t->week, t->weekday, day_names[t->weekday-1], + t->hour, t->minute, t->second); +} + +// Sane replacement for ctime(). +string datetime_short_name(int|void unix_time) +{ + mapping t = datetime(unix_time); + return sprintf("%04d-%02d-%02d %02d:%02d:%02d", + t->year, t->month, t->day, + t->hour, t->minute, t->second); +}