3 THIS IS A SUBSET OF THE FULL LIBTAI. CHANGES HAVE BEEN MADE TO SUIT
4 LIBKUMU STYLE AND TYPE CONVENTIONS. ALL BUGS BELONG TO JOHN HURST.
5 THE FOLLOWING IS FOR ATTRIBUTION, THANK YOU MR. BERNSTEIN FOR WRITING
6 AND DISTRIBUTING SUCH GREAT SOFTWARE:
11 D. J. Bernstein, djb@pobox.com
12 http://pobox.com/~djb/libtai.html
15 libtai is a library for storing and manipulating dates and times.
17 libtai supports two time scales: (1) TAI64, covering a few hundred
18 billion years with 1-second precision; (2) TAI64NA, covering the same
19 period with 1-attosecond precision. Both scales are defined in terms of
20 TAI, the current international real time standard.
22 libtai provides an internal format for TAI64, struct tai, designed for
23 fast time manipulations. The tai_pack() and tai_unpack() routines
24 convert between struct tai and a portable 8-byte TAI64 storage format.
25 libtai provides similar internal and external formats for TAI64NA.
27 libtai provides struct caldate to store dates in year-month-day form. It
28 can convert struct caldate, under the Gregorian calendar, to a modified
29 Julian day number for easy date arithmetic.
31 libtai provides struct caltime to store calendar dates and times along
32 with UTC offsets. It can convert from struct tai to struct caltime in
33 UTC, accounting for leap seconds, for accurate date and time display. It
34 can also convert back from struct caltime to struct tai for user input.
35 Its overall UTC-to-TAI conversion speed is 100x better than the usual
36 UNIX mktime() implementation.
38 This version of libtai requires a UNIX system with gettimeofday(). It
39 will be easy to port to other operating systems with compilers
40 supporting 64-bit arithmetic.
42 The libtai source code is in the public domain.
47 \version $Id: KM_tai.cpp,v 1.5 2012/03/07 17:30:52 mikey Exp $
48 \brief portable time functions
60 caldate_frommjd(Kumu::TAI::caldate* cd, i32_t day)
63 i32_t year, month, yday;
68 while (day >= 146097L) { day -= 146097L; ++year; }
70 /* year * 146097 + day - 678881 is MJD; 0 <= day < 146097 */
71 /* 2000-03-01, MJD 51604, is year 5, day 0 */
74 if (day == 146096L) { year += 3; day = 36524L; }
75 else { year += day / 36524L; day %= 36524L; }
82 if (day == 1460) { year += 3; day = 365; }
83 else { year += day / 365; day %= 365; }
87 month = (day + 5) / 306;
88 day = (day + 5) % 306;
90 if (month >= 10) { yday -= 306; ++year; month -= 10; }
91 else { yday += 59; month += 2; }
94 cd->month = month + 1;
99 static ui32_t times365[4] = { 0, 365, 730, 1095 } ;
100 static ui32_t times36524[4] = { 0, 36524UL, 73048UL, 109572UL } ;
101 static ui32_t montab[12] =
102 { 0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337 } ;
103 /* month length after february is (306 * m + 5) / 10 */
107 caldate_mjd(const Kumu::TAI::caldate* cd)
112 d = cd->day - 678882L;
116 d += 146097L * (y / 400);
119 if (m >= 2) m -= 2; else { m += 10; --y; }
123 if (m < 0) { m += 12; --y; }
127 d += 146097L * (y / 400);
129 if (y < 0) { y += 400; d -= 146097L; }
131 d += times365[y & 3];
134 d += 1461L * (y % 25);
137 d += times36524[y & 3];
145 caltime_utc(Kumu::TAI::caltime* ct, const Kumu::TAI::tai* t)
148 Kumu::TAI::tai t2 = *t;
149 ui64_t u = t2.x + 58486;
150 i32_t s = (i32_t)(u % ui64_C(86400));
152 ct->second = (s % 60); s /= 60;
153 ct->minute = s % 60; s /= 60;
157 caldate_frommjd(&ct->date,/*XXX*/(i32_t) (u - ui64_C(53375995543064)));
164 caltime_tai(const Kumu::TAI::caltime* ct, Kumu::TAI::tai* t)
169 /* XXX: check for overflow? */
171 day = caldate_mjd(&ct->date);
173 s = ct->hour * 60 + ct->minute;
174 s = (s - ct->offset) * 60 + ct->second;
176 t->x = day * ui64_C(86400) + ui64_C(4611686014920671114) + (i64_t)s;
181 Kumu::TAI::tai::now()
185 ::GetSystemTime(&st);
187 ct.date.year = st.wYear;
188 ct.date.month = st.wMonth;
189 ct.date.day = st.wDay;
191 ct.minute = st.wMinute;
192 ct.second = st.wSecond;
193 caltime_tai(&ct, this);
196 gettimeofday(&now, 0);
197 x = ui64_C(4611686018427387914) + (ui64_t)now.tv_sec;
203 const Kumu::TAI::tai&
204 Kumu::TAI::tai::operator=(const Kumu::TAI::caltime& rhs)
206 caltime_tai(&rhs, this);
211 const Kumu::TAI::caltime&
212 Kumu::TAI::caltime::operator=(const Kumu::TAI::tai& rhs)
214 caltime_utc(this, &rhs);