pike.git
/
lib
/
modules
/
Calendar.pmod
/
YMD.pike
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/lib/modules/Calendar.pmod/YMD.pike:1:
//! //! module Calendar //! submodule YMD //! //! base for all Roman-kind of Calendars, //! ie, one with years, months, weeks and days //!
+
//! inherits Time
#pike __REAL_VERSION__ // #pragma strict_types inherit Calendar.Time:Time; #include "constants.h" // ----------------
pike.git/lib/modules/Calendar.pmod/YMD.pike:37:
protected string f_week_day_shortname_from_number; protected string f_week_day_name_from_number; protected string f_year_name_from_number; protected string f_year_number_from_name; protected int(0..1) year_leap_year(int y); protected int compat_week_day(int n);
+
// Polynomial terms for calculating the difference between TDT and UTC.
+
//
+
// The polynomials have been taken from NASA:
+
// @url{http://eclipse.gsfc.nasa.gov/SEhelp/deltatpoly2004.html@}
+
//
+
// Each entry is an @expr{array(float)@}:
+
// @array
+
// @elem float 0
+
// End year for the range.
+
// @elem float 1
+
// Year offset.
+
// @elem float 2
+
// Year divisor.
+
// @elem float 3..
+
// Polynomial factors with the highest exponent first.
+
// @endarray
+
protected constant deltat_polynomials = ({
+
({ -500.0, -1820.0, 100.0,
+
-20.0, 0.0, 32.0, }),
+
({ 500.0, 0.0, 100.0,
+
0.0090316521, 0.022174192, -0.1798452,
+
-5.952053, 33.78311, -1014.41, 10583.6, }),
+
({ 1600.0, -1000.0, 100.0,
+
0.0083572073, -0.005050998, -0.8503463,
+
0.319781, 71.23472, -556.01, 1574.2, }),
+
({ 1700.0, -1600.0, 1.0,
+
0.000140272128, -0.01532, -0.9808, 120.0, }),
+
({ 1800.0, -1700.0, 1.0,
+
0.000000851788756, 0.00013336, -0.0059285, 0.1603, 8.83, }),
+
({ 1860.0, -1800.0, 1.0,
+
0.000000000875, -0.0000001699, 0.0000121272, -0.00037436,
+
0.0041116, 0.0068612, -0.332447, 13.72, }),
+
({ 1900.0, -1860.0, 1.0,
+
0.000004288643, -0.0004473624, 0.01680668, -0.251754, 0.5737, 7.62, }),
+
({ 1920.0, -1900.0, 1.0,
+
-0.000197, 0.0061966, -0.0598939, 1.494119, -2.79, }),
+
({ 1941.0, -1920.0, 1.0,
+
0.0020936, -0.076100, 0.84493, 21.20, }),
+
({ 1961.0, -1950.0, 1.0,
+
0.0003926188, 0.0042918455, 0.407, 29.07, }),
+
({ 1986.0, -1975.0, 1.0,
+
0.001392758, 0.0038461538, 1.067, 45.45, }),
+
({ 2005.0, -2000.0, 1.0,
+
0.00002373599, 0.000651814, 0.0017275, -0.060374, 0.3345, 63.86, }),
+
({ 2050.0, -2000.0, 1.0,
+
0.005589, 0.32217, 62.92 }),
+
({ 2150.0, -1820.0, 100.0,
+
32.0-185.724, 56.28, -20.0, }),
+
({ Math.inf, -1820.0, 100.0,
+
32.0, 0.0, -20.0, }),
+
});
+
+
//! method float deltat(int unadjusted_utc)
+
//! Terrestrial Dynamical Time difference from standard time.
+
//!
+
//! returns
+
//! An approximation of the difference between TDT and UTC
+
//! in fractional seconds at the specified time.
+
//!
+
//! The zero point is 1901-06-25T14:23:01 UTC
+
//! (unix time -2162281019), ie the accumulated number
+
//! of leap seconds since then is returned.
+
//!
+
//! note
+
//! The function is based on polynomials provided by NASA,
+
//! and the result may differ from actual for dates after 2004.
+
float deltat(int unadjusted_utc)
+
{
+
// Approximation of the year. This ought to be good enough for
+
// most purposes given the uncertainty in the table values.
+
// 31556952 == 365.2425 * 24 * 60 * 60.
+
float y = 1970.0 + unadjusted_utc/31556952.0;
+
+
array(float) polynomial;
+
int l, c, h = sizeof(deltat_polynomials);
+
do {
+
c = (l + h)/2;
+
polynomial = deltat_polynomials[c];
+
if (y < polynomial[0]) h = c;
+
else l = c + 1;
+
} while (l < h);
+
float u = (y + polynomial[1])/polynomial[2];
+
+
float deltat = 0.0;
+
foreach(polynomial; int i; float factor) {
+
if (i < 3) continue;
+
deltat = deltat * u + factor;
+
}
+
return deltat;
+
}
+
//------------------------------------------------------------------------ //! class YMD //! Base (virtual) time period of the Roman-kind of calendar. //! inherits TimeRange //------------------------------------------------------------------------ class YMD { inherit TimeRange;
pike.git/lib/modules/Calendar.pmod/YMD.pike:144:
//! method string week_name() //! method string year_name() //! method string tzname() //! method string tzname_iso() int julian_day() { return jd; }
-
//!
function
method int unix_time()
+
//! method int unix_time()
//! Returns the unix time integer corresponding to the start //! of the time range object. (An unix time integer is UTC.) int unix_time() { // 1970-01-01 is julian day 2440588 int ux=(jd-2440588)*86400; if (utco==CALUNKNOWN) [utco,tzn]=rules->timezone->tz_jd(jd); return ux+utco;
pike.git/lib/modules/Calendar.pmod/YMD.pike:269:
return rules->language[f_week_day_shortname_from_number](wd); } int leap_year() { return year_leap_year(year_no()); } int hour_no() { return 0; } int minute_no() { return 0; } int second_no() { return 0; } float fraction_no() { return 0.0; }
-
//!
function
method datetime()
+
//! method
mapping
datetime()
//! This gives back a mapping with the relevant //! time information (representing the start of the period); //! <pre> //! ([ "year": int // year number (2000 AD=2000, 1 BC==0) //! "month": int(1..) // month of year //! "day": int(1..) // day of month //! "yearday": int(0..) // day of year //! "week": int(1..) // week of year //! "week_day": int(0..) // day of week //! "timezone": int // offset to utc, including dst
pike.git/lib/modules/Calendar.pmod/YMD.pike:406:
//! todz "00:00:00 CET" //! todz_iso "00:00:00 UTC+1" //! xtod "00:00:00.000000" //! mod "00:00" //! </pre> //! <tt>[1]</tt> note conflict (think 1 February 2003) //! <br><tt>[2]</tt> language dependent //! <br><tt>[3]</tt> as from the libc function ctime() //! <br><tt>[4]</tt> as specified by the HTTP standard; //! not language dependent.
+
//!
+
//! The iso variants aim to be compliant with ISO-8601.
string format_iso_ymd() { if (m==CALUNKNOWN) make_month(); if (w==CALUNKNOWN) make_week(); return sprintf("%04d-%02d-%02d (%s) -W%02d-%d (%s)", y,m,md, month_shortname(), w,wd, // fixme - what weekday? week_day_shortname());
pike.git/lib/modules/Calendar.pmod/YMD.pike:1432:
} cYear set_ruleset(Calendar.Ruleset r) { return Year("ymd_y",r,y,yjd,n); } } // ----------------------------------------------------------------
-
//
Month
+
//
!
class
Month
+
//!
inherits YMD
// ---------------------------------------------------------------- function(mixed...:cMonth) Month=cMonth; class cMonth { inherit YMD; constant is_month=1; int nd; // number of days
pike.git/lib/modules/Calendar.pmod/YMD.pike:1723:
//! calendar, which modifies this rule for the Gregorian calendar; //! the week number and year is the same as for the ISO calendar, //! except for the sundays. //! //! When adding, moving and subtracting months //! to a week, it falls back to using days. //! //! When adding, moving or subtracting years, //! if tries to place the moved week in the //! resulting year.
+
//!
+
//! inherits YMD
// ---------------------------------------------------------------- function(mixed...:cWeek) Week=cWeek; class cWeek { inherit YMD; // Note: wy, w and wd are never CALUNKNOWN in this class. constant is_week=1;
pike.git/lib/modules/Calendar.pmod/YMD.pike:2061:
{ return Week("ymd_yjwm",r,y,yjd,jd,wy,w,n,md,m,mnd); } // --- needs to be defined protected int weeks_to_week(int y,int m); } // ----------------------------------------------------------------
-
//
Day
+
//
!
class
Day
+
//!
inherits YMD
// ---------------------------------------------------------------- class cDay { inherit YMD; constant is_day=1; int nw; //!
pike.git/lib/modules/Calendar.pmod/YMD.pike:2511:
//! inherits YMD //------------------------------------------------------------------------ class cHour { inherit Time::cHour; inherit YMD_Time; OVERLOAD_TIMEOFDAY; }
+
//------------------------------------------------------------------------
+
//! class Minute
+
//! inherits Time.Minute
+
//! inherits YMD
+
//------------------------------------------------------------------------
+
class cMinute { inherit Time::cMinute; inherit YMD_Time; OVERLOAD_TIMEOFDAY; }
-
+
//------------------------------------------------------------------------
+
//! class Second
+
//! inherits Time.Second
+
//! inherits YMD
+
//------------------------------------------------------------------------
+
class cSecond { inherit Time::cSecond; inherit YMD_Time; OVERLOAD_TIMEOFDAY; }
-
+
//------------------------------------------------------------------------
+
//! class Fraction
+
//! inherits Time.Fraction
+
//! inherits YMD
+
//------------------------------------------------------------------------
+
class cFraction { inherit Time::cFraction; inherit YMD_Time; OVERLOAD_TIMEOFDAY; }
-
+
//------------------------------------------------------------------------
+
//! class SuperTimeRange
+
//! inherits Time.SuperTimeRange
+
//------------------------------------------------------------------------
+
class cSuperTimeRange { inherit Time::cSuperTimeRange; array(cYear) years(int ...range) { return get_units("years",@range); } cYear year(void|int n) { return get_unit("years",n); } int number_of_years() { return num_units("years"); } array(cMonth) months(int ...range) { return get_units("months",@range); } cMonth month(void|int n) { return get_unit("months",n); }
pike.git/lib/modules/Calendar.pmod/YMD.pike:2584:
string format_iso_week_short() { return RBASE->format_iso_week_short(); } string format_week() { return RBASE->format_week(); } string format_week_short() { return RBASE->format_week_short(); } string format_month() { return RBASE->format_month(); } string format_month_short() { return RBASE->format_month_short(); } #undef RBASE } //------------------------------------------------------------------------
-
//! global
convinience
functions
+
//
Pop out doc-extractor context to the top-level scope.
+
//
!
module Calendar
+
//! submodule YMD
+
//
global
convenience
functions
//------------------------------------------------------------------------ //! method TimeRange parse(string fmt,string arg) //! parse a date, create relevant object //! fmt is in the format "abc%xdef..." //! where abc and def is matched, and %x is //! one of those time units: //! <pre> //! %Y absolute year //! %y dwim year (70-99 is 1970-1999, 0-69 is 2000-2069)
pike.git/lib/modules/Calendar.pmod/YMD.pike:2846:
{ m->month=low=m->year->month(m->M); } if (m->W) m->week=low=m->year->week("w"+m->W); if (!zero_type(m->D)) m->day=low=(m->month||(context?context->month():cal->Month())) ->day((int)m->D); else if (!zero_type(m->a))
-
m->day=low=m->year->day(m->a);
+
m->day=low=
(
m->
month || m->
year
)
->day(m->a);
else if (!zero_type(m->e)) m->day=low=(m->week||(context?context->week():cal->Week())) ->day(m->e); else low=m->day=context?context->day():cal->Day(); if (m->day && zero_type(m->Y) && zero_type(m->y) && m->e) if (m->month) { // scan for closest year that matches
pike.git/lib/modules/Calendar.pmod/YMD.pike:2939:
if (sub_second) low = low->fraction(sub_second); return low; #ifndef NOCATCH }) #endif return 0; }
-
//!
function
Day dwim_day(string date)
-
//!
function
Day dwim_day(string date,TimeRange context)
+
//!
method
Day dwim_day(string date)
+
//!
method
Day dwim_day(string date,TimeRange context)
//! Tries a number of different formats on the given date (in order): //! <pre> //! <ref>parse</ref> format as in //! "%y-%M-%D (%M) -W%W-%e (%e)" "2000-03-20 (Mar) -W12-1 (Mon)" //! "%y-%M-%D" "2000-03-20", "00-03-20" //! "%M%/%D/%y" "3/20/2000" //! "%D%*[ /]%M%*[ /-,]%y" "20/3/2000" "20 mar 2000" "20/3 -00" //! "%e%*[ ]%D%*[ /]%M%*[ /-,]%y" "Mon 20 Mar 2000" "Mon 20/3 2000" //! "-%y%*[ /]%D%*[ /]%M" "-00 20/3" "-00 20 mar" //! "-%y%*[ /]%M%*[ /]%D" "-00 3/20" "-00 march 20"
pike.git/lib/modules/Calendar.pmod/YMD.pike:3170:
(t=parse(rfc850_date, what, cx)) || (t=parse(asctime_date+" %z", what+" GMT", cx)) ) return t; return 0; } //-- auxillary functions------------------------------------------------ //!
-
//! function datetime(int|void unix_time)
+
//! function
mapping(string:int)
datetime(int|void unix_time)
//! Replacement for localtime; gives back a mapping: //! <pre> //! ([ "year": int // year number (2000 AD=2000, 1 BC==0) //! "month": int(1..) // month of year //! "day": int(1..) // day of month //! "yearday": int(1..) // day of year //! "week": int(1..) // week of year //! "week_day": int(1..) // day of week (depending on calendar) //! "unix": int // unix time //! "julian": float // julian day //! "hour": int(0..) // hour of day, including dst //! "minute": int(0..59) // minute of hour //! "second": int(0..59) // second of minute //! "fraction": float // fraction of second //! "timezone": int // offset to utc, including dst //! ]); //! </pre> //! This is the same as calling <ref>Second</ref>()-><ref to=Second.datetime>datetime</ref>(). //!
-
//! function datetime_name(int|void unix_time)
-
//! function datetime_short_name(int|void unix_time)
+
//! function
string
datetime_name(int|void unix_time)
+
//! function
string
datetime_short_name(int|void unix_time)
//! Compat functions; same as <ref>format_iso</ref> //! and <ref>format_iso_short</ref>. //! //! function string format_iso(void|int unix_time) //! function string format_iso_short(void|int unix_time) //! function string format_iso_tod(void|int unix_time) //! function string format_day_iso(void|int unix_time) //! function string format_day_iso_short(void|int unix_time) //! Format the object into nice strings; //! <pre>