Bv2.1 7.2.3: Check that subtitle <StartTime> exists and is 0.
[libdcp.git] / src / local_time.cc
index 2aa551836fdf2d8737b41956ee07d9c91410ba30..6a8579ffc495743c365157502297106767e7f3bf 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2014-2019 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2014-2020 Carl Hetherington <cth@carlh.net>
 
     This file is part of libdcp.
 
@@ -39,7 +39,9 @@
 #include "exceptions.h"
 #include "dcp_assert.h"
 #include <boost/lexical_cast.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
 #include <boost/date_time/c_local_time_adjustor.hpp>
+#include <boost/date_time/gregorian/gregorian.hpp>
 #include <cstdio>
 
 using std::string;
@@ -53,11 +55,13 @@ LocalTime::LocalTime ()
        time_t now = time (0);
        struct tm* tm = localtime (&now);
        set (tm);
+       set_local_time_zone ();
 }
 
 LocalTime::LocalTime (struct tm t)
 {
        set (&t);
+       set_local_time_zone ();
 }
 
 void
@@ -70,14 +74,19 @@ LocalTime::set (struct tm const * tm)
        _minute = tm->tm_min;
        _second = tm->tm_sec;
        _millisecond = 0;
-
-       set_local_time_zone ();
 }
 
 /** Construct a LocalTime from a boost::posix_time::ptime using the local
  *  time zone.
  */
 LocalTime::LocalTime (boost::posix_time::ptime t)
+{
+       set (t);
+       set_local_time_zone ();
+}
+
+void
+LocalTime::set (boost::posix_time::ptime t)
 {
        _year = t.date().year ();
        _month = t.date().month ();
@@ -87,8 +96,6 @@ LocalTime::LocalTime (boost::posix_time::ptime t)
        _second = t.time_of_day().seconds ();
        _millisecond = t.time_of_day().fractional_seconds () / 1000;
        DCP_ASSERT (_millisecond < 1000);
-
-       set_local_time_zone ();
 }
 
 /** Construct a LocalTime from a boost::posix_time::ptime and a time zone offset.
@@ -97,15 +104,7 @@ LocalTime::LocalTime (boost::posix_time::ptime t)
  */
 LocalTime::LocalTime (boost::posix_time::ptime t, int tz_hour, int tz_minute)
 {
-       _year = t.date().year ();
-       _month = t.date().month ();
-       _day = t.date().day ();
-       _hour = t.time_of_day().hours ();
-       _minute = t.time_of_day().minutes ();
-       _second = t.time_of_day().seconds ();
-       _millisecond = t.time_of_day().fractional_seconds () / 1000;
-       DCP_ASSERT (_millisecond < 1000);
-
+       set (t);
        _tz_hour = tz_hour;
        _tz_minute = tz_minute;
 }
@@ -218,20 +217,46 @@ LocalTime::time_of_day (bool with_second, bool with_millisecond) const
        return buffer;
 }
 
+
 void
-LocalTime::add_months (int m)
+LocalTime::add_days (int days)
 {
-       _month += m;
+       using namespace boost;
 
-       while (_month < 0) {
-               _month += 12;
-               _year--;
+       gregorian::date d (_year, _month, _day);
+       if (days > 0) {
+               d += gregorian::days (days);
+       } else {
+               d -= gregorian::days (-days);
        }
 
-       while (_month > 11) {
-               _month -= 12;
-               _year++;
+       set (posix_time::ptime(d, posix_time::time_duration(_hour, _minute, _second, _millisecond * 1000)));
+}
+
+
+void
+LocalTime::add_months (int m)
+{
+       using namespace boost;
+
+       gregorian::date d (_year, _month, _day);
+       if (m > 0) {
+               d += gregorian::months (m);
+       } else {
+               d -= gregorian::months (-m);
        }
+
+       set (posix_time::ptime(d, posix_time::time_duration(_hour, _minute, _second, _millisecond * 1000)));
+}
+
+void
+LocalTime::add_minutes (int m)
+{
+       using namespace boost;
+
+       posix_time::ptime t(gregorian::date(_year, _month, _day), posix_time::time_duration(_hour, _minute, _second, _millisecond * 1000));
+       t += posix_time::time_duration(0, m, 0);
+       set (t);
 }
 
 bool