summaryrefslogtreecommitdiff
path: root/asdcplib/src/KM_tai.cpp
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2015-01-14 17:39:32 +0000
committerCarl Hetherington <cth@carlh.net>2015-01-20 11:20:25 +0000
commit3f630fb8334238ab8a58fbe1a0f513ae2c00de80 (patch)
tree4b773b91029d6374bfd4f2194053d3e249d597cd /asdcplib/src/KM_tai.cpp
parent49cafda01b3e07c47e3b20dd5ee91e1426446aea (diff)
Simplify time representation; better in-tree DCP subtitle parser.
Diffstat (limited to 'asdcplib/src/KM_tai.cpp')
-rw-r--r--asdcplib/src/KM_tai.cpp221
1 files changed, 221 insertions, 0 deletions
diff --git a/asdcplib/src/KM_tai.cpp b/asdcplib/src/KM_tai.cpp
new file mode 100644
index 0000000..2cbd125
--- /dev/null
+++ b/asdcplib/src/KM_tai.cpp
@@ -0,0 +1,221 @@
+/*
+
+THIS IS A SUBSET OF THE FULL LIBTAI. CHANGES HAVE BEEN MADE TO SUIT
+LIBKUMU STYLE AND TYPE CONVENTIONS. ALL BUGS BELONG TO JOHN HURST.
+THE FOLLOWING IS FOR ATTRIBUTION, THANK YOU MR. BERNSTEIN FOR WRITING
+AND DISTRIBUTING SUCH GREAT SOFTWARE:
+
+libtai 0.60, alpha.
+19981013
+Copyright 1998
+D. J. Bernstein, djb@pobox.com
+http://pobox.com/~djb/libtai.html
+
+
+libtai is a library for storing and manipulating dates and times.
+
+libtai supports two time scales: (1) TAI64, covering a few hundred
+billion years with 1-second precision; (2) TAI64NA, covering the same
+period with 1-attosecond precision. Both scales are defined in terms of
+TAI, the current international real time standard.
+
+libtai provides an internal format for TAI64, struct tai, designed for
+fast time manipulations. The tai_pack() and tai_unpack() routines
+convert between struct tai and a portable 8-byte TAI64 storage format.
+libtai provides similar internal and external formats for TAI64NA.
+
+libtai provides struct caldate to store dates in year-month-day form. It
+can convert struct caldate, under the Gregorian calendar, to a modified
+Julian day number for easy date arithmetic.
+
+libtai provides struct caltime to store calendar dates and times along
+with UTC offsets. It can convert from struct tai to struct caltime in
+UTC, accounting for leap seconds, for accurate date and time display. It
+can also convert back from struct caltime to struct tai for user input.
+Its overall UTC-to-TAI conversion speed is 100x better than the usual
+UNIX mktime() implementation.
+
+This version of libtai requires a UNIX system with gettimeofday(). It
+will be easy to port to other operating systems with compilers
+supporting 64-bit arithmetic.
+
+The libtai source code is in the public domain.
+
+*/
+
+ /*! \file KM_tai.cpp
+ \version $Id: KM_tai.cpp,v 1.5 2012/03/07 17:30:52 mikey Exp $
+ \brief portable time functions
+ */
+
+#include <KM_tai.h>
+#ifdef KM_WIN32
+#include <time.h>
+#else
+#include <sys/time.h>
+#endif
+
+//
+void
+caldate_frommjd(Kumu::TAI::caldate* cd, i32_t day)
+{
+ assert(cd);
+ i32_t year, month, yday;
+
+ year = day / 146097L;
+ day %= 146097L;
+ day += 678881L;
+ while (day >= 146097L) { day -= 146097L; ++year; }
+
+ /* year * 146097 + day - 678881 is MJD; 0 <= day < 146097 */
+ /* 2000-03-01, MJD 51604, is year 5, day 0 */
+
+ year *= 4;
+ if (day == 146096L) { year += 3; day = 36524L; }
+ else { year += day / 36524L; day %= 36524L; }
+ year *= 25;
+ year += day / 1461;
+ day %= 1461;
+ year *= 4;
+
+ yday = (day < 306);
+ if (day == 1460) { year += 3; day = 365; }
+ else { year += day / 365; day %= 365; }
+ yday += day;
+
+ day *= 10;
+ month = (day + 5) / 306;
+ day = (day + 5) % 306;
+ day /= 10;
+ if (month >= 10) { yday -= 306; ++year; month -= 10; }
+ else { yday += 59; month += 2; }
+
+ cd->year = year;
+ cd->month = month + 1;
+ cd->day = day + 1;
+}
+
+//
+static ui32_t times365[4] = { 0, 365, 730, 1095 } ;
+static ui32_t times36524[4] = { 0, 36524UL, 73048UL, 109572UL } ;
+static ui32_t montab[12] =
+{ 0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337 } ;
+/* month length after february is (306 * m + 5) / 10 */
+
+//
+i32_t
+caldate_mjd(const Kumu::TAI::caldate* cd)
+{
+ assert(cd);
+ i32_t y, m, d;
+
+ d = cd->day - 678882L;
+ m = cd->month - 1;
+ y = cd->year;
+
+ d += 146097L * (y / 400);
+ y %= 400;
+
+ if (m >= 2) m -= 2; else { m += 10; --y; }
+
+ y += (m / 12);
+ m %= 12;
+ if (m < 0) { m += 12; --y; }
+
+ d += montab[m];
+
+ d += 146097L * (y / 400);
+ y %= 400;
+ if (y < 0) { y += 400; d -= 146097L; }
+
+ d += times365[y & 3];
+ y >>= 2;
+
+ d += 1461L * (y % 25);
+ y /= 25;
+
+ d += times36524[y & 3];
+
+ return d;
+}
+
+
+//
+void
+caltime_utc(Kumu::TAI::caltime* ct, const Kumu::TAI::tai* t)
+{
+ assert(ct&&t);
+ Kumu::TAI::tai t2 = *t;
+ ui64_t u = t2.x + 58486;
+ i32_t s = (i32_t)(u % ui64_C(86400));
+
+ ct->second = (s % 60); s /= 60;
+ ct->minute = s % 60; s /= 60;
+ ct->hour = s;
+
+ u /= ui64_C(86400);
+ caldate_frommjd(&ct->date,/*XXX*/(i32_t) (u - ui64_C(53375995543064)));
+
+ ct->offset = 0;
+}
+
+//
+void
+caltime_tai(const Kumu::TAI::caltime* ct, Kumu::TAI::tai* t)
+{
+ assert(ct&&t);
+ i32_t day, s;
+
+ /* XXX: check for overflow? */
+
+ day = caldate_mjd(&ct->date);
+
+ s = ct->hour * 60 + ct->minute;
+ s = (s - ct->offset) * 60 + ct->second;
+
+ t->x = day * ui64_C(86400) + ui64_C(4611686014920671114) + (i64_t)s;
+}
+
+//
+void
+Kumu::TAI::tai::now()
+{
+#ifdef KM_WIN32
+ SYSTEMTIME st;
+ ::GetSystemTime(&st);
+ TAI::caltime ct;
+ ct.date.year = st.wYear;
+ ct.date.month = st.wMonth;
+ ct.date.day = st.wDay;
+ ct.hour = st.wHour;
+ ct.minute = st.wMinute;
+ ct.second = st.wSecond;
+ caltime_tai(&ct, this);
+#else
+ struct timeval now;
+ gettimeofday(&now, 0);
+ x = ui64_C(4611686018427387914) + (ui64_t)now.tv_sec;
+#endif
+}
+
+
+//
+const Kumu::TAI::tai&
+Kumu::TAI::tai::operator=(const Kumu::TAI::caltime& rhs)
+{
+ caltime_tai(&rhs, this);
+ return *this;
+}
+
+//
+const Kumu::TAI::caltime&
+Kumu::TAI::caltime::operator=(const Kumu::TAI::tai& rhs)
+{
+ caltime_utc(this, &rhs);
+ return *this;
+}
+
+
+//
+// end KM_tai.cpp
+//