Add call to parent constructor.
[asdcplib-cth.git] / src / KM_tai.cpp
1 /*
2
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:
7
8 libtai 0.60, alpha.
9 19981013
10 Copyright 1998
11 D. J. Bernstein, djb@pobox.com
12 http://pobox.com/~djb/libtai.html
13
14
15 libtai is a library for storing and manipulating dates and times.
16
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.
21
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.
26
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.
30
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.
37
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.
41
42 The libtai source code is in the public domain.
43
44 */
45
46   /*! \file    KM_tai.cpp
47     \version $Id: KM_tai.cpp,v 1.5 2012/03/07 17:30:52 mikey Exp $
48     \brief   portable time functions
49   */
50
51 #include <KM_tai.h>
52 #ifdef KM_WIN32
53 #include <time.h>
54 #else
55 #include <sys/time.h>
56 #endif
57
58 //
59 void
60 caldate_frommjd(Kumu::TAI::caldate* cd, i32_t day)
61 {
62   assert(cd);
63   i32_t year, month, yday;
64
65   year = day / 146097L;
66   day %= 146097L;
67   day += 678881L;
68   while (day >= 146097L) { day -= 146097L; ++year; }
69
70   /* year * 146097 + day - 678881 is MJD; 0 <= day < 146097 */
71   /* 2000-03-01, MJD 51604, is year 5, day 0 */
72
73   year *= 4;
74   if (day == 146096L) { year += 3; day = 36524L; }
75   else { year += day / 36524L; day %= 36524L; }
76   year *= 25;
77   year += day / 1461;
78   day %= 1461;
79   year *= 4;
80
81   yday = (day < 306);
82   if (day == 1460) { year += 3; day = 365; }
83   else { year += day / 365; day %= 365; }
84   yday += day;
85
86   day *= 10;
87   month = (day + 5) / 306;
88   day = (day + 5) % 306;
89   day /= 10;
90   if (month >= 10) { yday -= 306; ++year; month -= 10; }
91   else { yday += 59; month += 2; }
92
93   cd->year = year;
94   cd->month = month + 1;
95   cd->day = day + 1;
96 }
97
98 //
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 */
104
105 //
106 i32_t
107 caldate_mjd(const Kumu::TAI::caldate* cd)
108 {
109   assert(cd);
110   i32_t y, m, d;
111
112   d = cd->day - 678882L;
113   m = cd->month - 1;
114   y = cd->year;
115
116   d += 146097L * (y / 400);
117   y %= 400;
118
119   if (m >= 2) m -= 2; else { m += 10; --y; }
120
121   y += (m / 12);
122   m %= 12;
123   if (m < 0) { m += 12; --y; }
124
125   d += montab[m];
126
127   d += 146097L * (y / 400);
128   y %= 400;
129   if (y < 0) { y += 400; d -= 146097L; }
130
131   d += times365[y & 3];
132   y >>= 2;
133
134   d += 1461L * (y % 25);
135   y /= 25;
136
137   d += times36524[y & 3];
138
139   return d;
140 }
141
142
143 //
144 void
145 caltime_utc(Kumu::TAI::caltime* ct, const Kumu::TAI::tai* t)
146 {
147   assert(ct&&t);
148   Kumu::TAI::tai t2 = *t;
149   ui64_t u = t2.x + 58486;
150   i32_t s = (i32_t)(u % ui64_C(86400));
151
152   ct->second = (s % 60); s /= 60;
153   ct->minute = s % 60; s /= 60;
154   ct->hour = s;
155
156   u /= ui64_C(86400);
157   caldate_frommjd(&ct->date,/*XXX*/(i32_t) (u - ui64_C(53375995543064)));
158
159   ct->offset = 0;
160 }
161
162 //
163 void
164 caltime_tai(const Kumu::TAI::caltime* ct, Kumu::TAI::tai* t)
165 {
166   assert(ct&&t);
167   i32_t day, s;
168
169   /* XXX: check for overflow? */
170
171   day = caldate_mjd(&ct->date);
172
173   s = ct->hour * 60 + ct->minute;
174   s = (s - ct->offset) * 60 + ct->second;
175
176   t->x = day * ui64_C(86400) + ui64_C(4611686014920671114) + (i64_t)s;
177 }
178
179 //
180 void
181 Kumu::TAI::tai::now()
182 {
183 #ifdef KM_WIN32
184   SYSTEMTIME st;
185   ::GetSystemTime(&st);
186   TAI::caltime ct;
187   ct.date.year = st.wYear;
188   ct.date.month = st.wMonth;
189   ct.date.day = st.wDay;
190   ct.hour = st.wHour;
191   ct.minute = st.wMinute;
192   ct.second = st.wSecond;
193   caltime_tai(&ct, this);
194 #else
195   struct timeval now;
196   gettimeofday(&now, 0);
197   x = ui64_C(4611686018427387914) + (ui64_t)now.tv_sec;
198 #endif
199 }
200
201
202 //
203 const Kumu::TAI::tai&
204 Kumu::TAI::tai::operator=(const Kumu::TAI::caltime& rhs)
205 {
206   caltime_tai(&rhs, this);
207   return *this;
208 }
209
210 //
211 const Kumu::TAI::caltime&
212 Kumu::TAI::caltime::operator=(const Kumu::TAI::tai& rhs)
213 {
214   caltime_utc(this, &rhs);
215   return *this;
216 }
217
218
219 //
220 // end KM_tai.cpp
221 //