Fix check for return value of EssenceType.
[libdcp.git] / test / local_time_test.cc
1 /*
2     Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
3
4     This file is part of libdcp.
5
6     libdcp is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     libdcp is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with libdcp.  If not, see <http://www.gnu.org/licenses/>.
18
19     In addition, as a special exception, the copyright holders give
20     permission to link the code of portions of this program with the
21     OpenSSL library under certain conditions as described in each
22     individual source file, and distribute linked combinations
23     including the two.
24
25     You must obey the GNU General Public License in all respects
26     for all of the code used other than OpenSSL.  If you modify
27     file(s) with this exception, you may extend this exception to your
28     version of the file(s), but you are not obligated to do so.  If you
29     do not wish to do so, delete this exception statement from your
30     version.  If you delete this exception statement from all source
31     files in the program, then also delete it here.
32 */
33
34
35 #include "exceptions.h"
36 #include "local_time.h"
37 #include <boost/test/unit_test.hpp>
38
39
40 /** Check that dcp::LocalTime works */
41 BOOST_AUTO_TEST_CASE (local_time_basic_test)
42 {
43         /* Badly-formatted times */
44         BOOST_CHECK_THROW (dcp::LocalTime (""), dcp::TimeFormatError);
45         BOOST_CHECK_THROW (dcp::LocalTime ("XXX"), dcp::TimeFormatError);
46         BOOST_CHECK_THROW (dcp::LocalTime ("2013-01-05T18:06:59+04:0"), dcp::TimeFormatError);
47         BOOST_CHECK_THROW (dcp::LocalTime ("2013-01-05T18:06:59X04:00"), dcp::TimeFormatError);
48         BOOST_CHECK_THROW (dcp::LocalTime ("2013-01-05T18-06:59+04:00"), dcp::TimeFormatError);
49         BOOST_CHECK_THROW (dcp::LocalTime ("2013!01-05T18:06:59+04:00"), dcp::TimeFormatError);
50
51         /* Correctly-formatted */
52
53         {
54                 dcp::LocalTime t("2013-01-05T18:06:59");
55                 BOOST_CHECK_EQUAL(t._year, 2013);
56                 BOOST_CHECK_EQUAL(t._month, 1);
57                 BOOST_CHECK_EQUAL(t._day, 5);
58                 BOOST_CHECK_EQUAL(t._hour, 18);
59                 BOOST_CHECK_EQUAL(t._minute, 6);
60                 BOOST_CHECK_EQUAL(t._second, 59);
61                 BOOST_CHECK(t._offset == dcp::UTCOffset(0, 0));
62                 BOOST_CHECK_EQUAL(t.as_string(), "2013-01-05T18:06:59+00:00");
63         }
64
65         {
66                 dcp::LocalTime t ("2013-01-05T18:06:59+04:00");
67                 BOOST_CHECK_EQUAL (t._year, 2013);
68                 BOOST_CHECK_EQUAL (t._month, 1);
69                 BOOST_CHECK_EQUAL (t._day, 5);
70                 BOOST_CHECK_EQUAL (t._hour, 18);
71                 BOOST_CHECK_EQUAL (t._minute, 6);
72                 BOOST_CHECK_EQUAL (t._second, 59);
73                 BOOST_CHECK(t._offset == dcp::UTCOffset(4, 0));
74                 BOOST_CHECK_EQUAL (t.as_string(), "2013-01-05T18:06:59+04:00");
75         }
76
77         {
78                 dcp::LocalTime t ("2011-11-20T01:06:59-09:30");
79                 BOOST_CHECK_EQUAL (t._year, 2011);
80                 BOOST_CHECK_EQUAL (t._month, 11);
81                 BOOST_CHECK_EQUAL (t._day, 20);
82                 BOOST_CHECK_EQUAL (t._hour, 1);
83                 BOOST_CHECK_EQUAL (t._minute, 6);
84                 BOOST_CHECK_EQUAL (t._second, 59);
85                 BOOST_CHECK(t._offset == dcp::UTCOffset(-9, -30));
86                 BOOST_CHECK_EQUAL (t.as_string(), "2011-11-20T01:06:59-09:30");
87         }
88
89         {
90                 dcp::LocalTime t ("2011-11-20T01:06:59.456-09:30");
91                 BOOST_CHECK_EQUAL (t._year, 2011);
92                 BOOST_CHECK_EQUAL (t._month, 11);
93                 BOOST_CHECK_EQUAL (t._day, 20);
94                 BOOST_CHECK_EQUAL (t._hour, 1);
95                 BOOST_CHECK_EQUAL (t._minute, 6);
96                 BOOST_CHECK_EQUAL (t._second, 59);
97                 BOOST_CHECK_EQUAL (t._millisecond, 456);
98                 BOOST_CHECK(t._offset == dcp::UTCOffset(-9, -30));
99                 BOOST_CHECK_EQUAL (t.as_string(true), "2011-11-20T01:06:59.456-09:30");
100         }
101
102         {
103                 dcp::LocalTime t ("2011-11-20T01:06:59.456-09:30");
104                 BOOST_CHECK_EQUAL (t._year, 2011);
105                 BOOST_CHECK_EQUAL (t._month, 11);
106                 BOOST_CHECK_EQUAL (t._day, 20);
107                 BOOST_CHECK_EQUAL (t._hour, 1);
108                 BOOST_CHECK_EQUAL (t._minute, 6);
109                 BOOST_CHECK_EQUAL (t._second, 59);
110                 BOOST_CHECK_EQUAL (t._millisecond, 456);
111                 BOOST_CHECK(t._offset == dcp::UTCOffset(-9, -30));
112                 BOOST_CHECK_EQUAL (t.as_string(true, false), "2011-11-20T01:06:59.456");
113         }
114
115         {
116                 dcp::LocalTime t ("2011-11-20T01:06:59.456-09:30");
117                 BOOST_CHECK_EQUAL (t._year, 2011);
118                 BOOST_CHECK_EQUAL (t._month, 11);
119                 BOOST_CHECK_EQUAL (t._day, 20);
120                 BOOST_CHECK_EQUAL (t._hour, 1);
121                 BOOST_CHECK_EQUAL (t._minute, 6);
122                 BOOST_CHECK_EQUAL (t._second, 59);
123                 BOOST_CHECK_EQUAL (t._millisecond, 456);
124                 BOOST_CHECK(t._offset == dcp::UTCOffset(-9, -30));
125                 BOOST_CHECK_EQUAL (t.as_string(false, false), "2011-11-20T01:06:59");
126         }
127
128         {
129                 dcp::LocalTime t("2011-11-20T01:06:59.45678901-09:30");
130                 BOOST_CHECK_EQUAL(t._year, 2011);
131                 BOOST_CHECK_EQUAL(t._month, 11);
132                 BOOST_CHECK_EQUAL(t._day, 20);
133                 BOOST_CHECK_EQUAL(t._hour, 1);
134                 BOOST_CHECK_EQUAL(t._minute, 6);
135                 BOOST_CHECK_EQUAL(t._second, 59);
136                 /* The fractional seconds here is truncated rather than rounded, for better or worse */
137                 BOOST_CHECK_EQUAL(t._millisecond, 456);
138                 BOOST_CHECK(t._offset == dcp::UTCOffset(-9, -30));
139                 BOOST_CHECK_EQUAL(t.as_string(false, false), "2011-11-20T01:06:59");
140         }
141
142         {
143                 dcp::LocalTime t("2024-01-23T23:21:32Z");
144                 BOOST_CHECK_EQUAL(t._year, 2024);
145                 BOOST_CHECK_EQUAL(t._month, 1);
146                 BOOST_CHECK_EQUAL(t._day, 23);
147                 BOOST_CHECK_EQUAL(t._hour, 23);
148                 BOOST_CHECK_EQUAL(t._minute, 21);
149                 BOOST_CHECK_EQUAL(t._second, 32);
150                 BOOST_CHECK_EQUAL(t._millisecond, 0);
151                 BOOST_CHECK(t._offset == dcp::UTCOffset(0, 0));
152                 BOOST_CHECK_EQUAL(t.as_string(false, false), "2024-01-23T23:21:32");
153         }
154
155         {
156                 /* Construction from boost::posix_time::ptime */
157                 dcp::LocalTime b (boost::posix_time::time_from_string ("2002-01-20 19:03:56"));
158                 BOOST_CHECK_EQUAL (b._year, 2002);
159                 BOOST_CHECK_EQUAL (b._month, 1);
160                 BOOST_CHECK_EQUAL (b._day, 20);
161                 BOOST_CHECK_EQUAL (b._hour, 19);
162                 BOOST_CHECK_EQUAL (b._minute, 3);
163                 BOOST_CHECK_EQUAL (b._second, 56);
164         }
165
166         {
167                 /* Construction from boost::posix_time::ptime with milliseconds */
168                 dcp::LocalTime b (boost::posix_time::time_from_string ("2002-01-20 19:03:56.491"));
169                 BOOST_CHECK_EQUAL (b._year, 2002);
170                 BOOST_CHECK_EQUAL (b._month, 1);
171                 BOOST_CHECK_EQUAL (b._day, 20);
172                 BOOST_CHECK_EQUAL (b._hour, 19);
173                 BOOST_CHECK_EQUAL (b._minute, 3);
174                 BOOST_CHECK_EQUAL (b._second, 56);
175                 BOOST_CHECK_EQUAL (b._millisecond, 491);
176         }
177
178         {
179                 dcp::LocalTime b ("2015-11-18T19:26:45");
180                 BOOST_CHECK_EQUAL (b._year, 2015);
181                 BOOST_CHECK_EQUAL (b._month, 11);
182                 BOOST_CHECK_EQUAL (b._day, 18);
183                 BOOST_CHECK_EQUAL (b._hour, 19);
184                 BOOST_CHECK_EQUAL (b._minute, 26);
185                 BOOST_CHECK_EQUAL (b._second, 45);
186                 BOOST_CHECK_EQUAL (b._millisecond, 0);
187                 BOOST_CHECK(b._offset == dcp::UTCOffset());
188         }
189
190         /* Check negative times with non-zero timezone offset minutes */
191         {
192                 dcp::LocalTime t ("2013-01-05T18:06:59-04:30");
193                 BOOST_CHECK_EQUAL (t._year, 2013);
194                 BOOST_CHECK_EQUAL (t._month, 1);
195                 BOOST_CHECK_EQUAL (t._day, 5);
196                 BOOST_CHECK_EQUAL (t._hour, 18);
197                 BOOST_CHECK_EQUAL (t._minute, 6);
198                 BOOST_CHECK_EQUAL (t._second, 59);
199                 BOOST_CHECK(t._offset == dcp::UTCOffset(-4, -30));
200                 BOOST_CHECK_EQUAL (t.as_string(), "2013-01-05T18:06:59-04:30");
201         }
202
203         /* KDM seen with a TZ offset of -07:59, which we used to reject because
204          * we only accepted minutes between -30 and +30 (for some reason that I
205          * now can't find).
206          */
207         {
208                 dcp::LocalTime t("2023-11-30T23:59:00-07:59");
209                 BOOST_CHECK_EQUAL(t._year, 2023);
210                 BOOST_CHECK_EQUAL(t._month, 11);
211                 BOOST_CHECK_EQUAL(t._day, 30);
212                 BOOST_CHECK_EQUAL(t._hour, 23);
213                 BOOST_CHECK_EQUAL(t._minute, 59);
214                 BOOST_CHECK_EQUAL(t._second, 00);
215                 BOOST_CHECK(t._offset == dcp::UTCOffset(-7, -59));
216                 BOOST_CHECK_EQUAL(t.as_string(), "2023-11-30T23:59:00-07:59");
217         }
218 }
219
220
221 BOOST_AUTO_TEST_CASE (local_time_add_minutes_test)
222 {
223         {
224                 dcp::LocalTime t("2018-01-01T10:00:00+01:00");
225                 t.add_minutes (3);
226                 BOOST_CHECK_EQUAL (t.as_string(), "2018-01-01T10:03:00+01:00");
227         }
228
229         {
230                 dcp::LocalTime t("2018-01-01T10:00:15+01:00");
231                 t.add_minutes (3);
232                 BOOST_CHECK_EQUAL (t.as_string(), "2018-01-01T10:03:15+01:00");
233         }
234
235         {
236                 dcp::LocalTime t("2018-01-01T10:40:20+01:00");
237                 t.add_minutes (23);
238                 BOOST_CHECK_EQUAL (t.as_string(), "2018-01-01T11:03:20+01:00");
239         }
240
241         {
242                 dcp::LocalTime t("2018-01-01T10:40:20+01:00");
243                 t.add_minutes (123);
244                 BOOST_CHECK_EQUAL (t.as_string(), "2018-01-01T12:43:20+01:00");
245         }
246
247         {
248                 dcp::LocalTime t("2018-01-01T23:55:00+01:00");
249                 t.add_minutes (7);
250                 BOOST_CHECK_EQUAL (t.as_string(), "2018-01-02T00:02:00+01:00");
251         }
252
253         {
254                 dcp::LocalTime t("2018-01-31T23:55:00+01:00");
255                 t.add_minutes (7);
256                 BOOST_CHECK_EQUAL (t.as_string(), "2018-02-01T00:02:00+01:00");
257         }
258
259         {
260                 dcp::LocalTime t("2018-01-31T23:55:00.123");
261                 t.add_minutes (7);
262                 BOOST_CHECK_EQUAL (t, dcp::LocalTime("2018-02-01T00:02:00.123"));
263         }
264 }
265
266
267 BOOST_AUTO_TEST_CASE (local_time_add_months_test)
268 {
269         {
270                 dcp::LocalTime t("2013-06-23T18:06:59.123");
271                 t.add_months(-1);
272                 BOOST_CHECK_EQUAL (t, dcp::LocalTime("2013-05-23T18:06:59.123"));
273                 t.add_months(1);
274                 BOOST_CHECK_EQUAL (t, dcp::LocalTime("2013-06-23T18:06:59.123"));
275                 t.add_months(1);
276                 BOOST_CHECK_EQUAL (t, dcp::LocalTime("2013-07-23T18:06:59.123"));
277                 t.add_months(4);
278                 BOOST_CHECK_EQUAL (t, dcp::LocalTime("2013-11-23T18:06:59.123"));
279                 t.add_months(2);
280                 BOOST_CHECK_EQUAL (t, dcp::LocalTime("2014-01-23T18:06:59.123"));
281                 t.add_months(-14);
282                 BOOST_CHECK_EQUAL (t, dcp::LocalTime("2012-11-23T18:06:59.123"));
283                 t.add_months(14);
284                 BOOST_CHECK_EQUAL (t, dcp::LocalTime("2014-01-23T18:06:59.123"));
285         }
286
287         {
288                 dcp::LocalTime t("2018-01-30T11:00:00+01:00");
289                 t.add_months (1);
290                 BOOST_CHECK_EQUAL (t.as_string(), "2018-02-28T11:00:00+01:00");
291         }
292 }
293
294
295 BOOST_AUTO_TEST_CASE (local_time_from_asn1_utctime_test)
296 {
297         BOOST_CHECK_EQUAL (dcp::LocalTime::from_asn1_utc_time("991231235952").as_string(), "1999-12-31T23:59:52+00:00");
298         BOOST_CHECK_EQUAL (dcp::LocalTime::from_asn1_utc_time("210215165952").as_string(), "2021-02-15T16:59:52+00:00");
299 }
300
301
302 BOOST_AUTO_TEST_CASE (local_time_from_asn1_generalized_time_test)
303 {
304         BOOST_CHECK_EQUAL (dcp::LocalTime::from_asn1_generalized_time("19991231235952").as_string(), "1999-12-31T23:59:52+00:00");
305         BOOST_CHECK_EQUAL (dcp::LocalTime::from_asn1_generalized_time("20210215165952").as_string(), "2021-02-15T16:59:52+00:00");
306 }
307
308
309 BOOST_AUTO_TEST_CASE(local_time_comparison_test)
310 {
311         BOOST_CHECK(dcp::LocalTime("2014-01-01T10:00:00") < dcp::LocalTime("2014-01-01T10:05:00"));
312         BOOST_CHECK(dcp::LocalTime("2014-01-01T10:00:00") < dcp::LocalTime("2015-01-01T10:00:00"));
313         BOOST_CHECK(dcp::LocalTime("2014-01-01T10:00:00") < dcp::LocalTime("2014-01-01T11:00:00"));
314         BOOST_CHECK(dcp::LocalTime("2014-10-10T10:00:00") < dcp::LocalTime("2014-10-10T10:00:01"));
315         BOOST_CHECK(!(dcp::LocalTime("2014-10-10T10:00:00") < dcp::LocalTime("2014-10-10T10:00:00")));
316         BOOST_CHECK(dcp::LocalTime("2014-10-10T10:00:00+01:00") < dcp::LocalTime("2014-10-10T10:00:00"));
317         BOOST_CHECK(dcp::LocalTime("2014-10-10T10:00:00+01:30") < dcp::LocalTime("2014-10-10T10:00:00"));
318         BOOST_CHECK(dcp::LocalTime("2014-10-10T10:00:00+01:00") < dcp::LocalTime("2014-10-10T10:00:01+01:00"));
319         BOOST_CHECK(dcp::LocalTime("2014-01-01T10:00:00") < dcp::LocalTime("2014-01-01T10:05:00"));
320         BOOST_CHECK(dcp::LocalTime("2014-10-10T10:00:00") < dcp::LocalTime("2014-10-10T10:00:00-01:30"));
321
322         BOOST_CHECK(dcp::LocalTime("2014-01-01T10:05:00") > dcp::LocalTime("2014-01-01T10:00:00"));
323         BOOST_CHECK(dcp::LocalTime("2014-10-10T10:00:00-01:30") > dcp::LocalTime("2014-10-10T10:00:00"));
324         BOOST_CHECK(dcp::LocalTime("2014-01-01T10:05:00") > dcp::LocalTime("2014-01-01T10:00:00"));
325         BOOST_CHECK(dcp::LocalTime("2015-01-01T10:00:00") > dcp::LocalTime("2014-01-01T10:00:00"));
326         BOOST_CHECK(dcp::LocalTime("2014-01-01T11:00:00") > dcp::LocalTime("2014-01-01T10:00:00"));
327         BOOST_CHECK(dcp::LocalTime("2014-10-10T10:00:01") > dcp::LocalTime("2014-10-10T10:00:00"));
328         BOOST_CHECK(!(dcp::LocalTime("2014-10-10T10:00:00") > dcp::LocalTime("2014-10-10T10:00:00")));
329         BOOST_CHECK(dcp::LocalTime("2014-10-10T10:00:00") > dcp::LocalTime("2014-10-10T10:00:00+01:00"));
330         BOOST_CHECK(dcp::LocalTime("2014-10-10T10:00:00") > dcp::LocalTime("2014-10-10T10:00:00+01:30"));
331         BOOST_CHECK(dcp::LocalTime("2014-10-10T10:00:01+01:00") > dcp::LocalTime("2014-10-10T10:00:00+01:00"));
332
333         BOOST_CHECK(dcp::LocalTime("2014-01-01T10:00:00") != dcp::LocalTime("2014-01-01T10:05:00"));
334         BOOST_CHECK(dcp::LocalTime("2014-01-01T10:00:00") == dcp::LocalTime("2014-01-01T10:00:00"));
335         BOOST_CHECK(dcp::LocalTime("2014-01-01T10:00:00+02:00") == dcp::LocalTime("2014-01-01T08:00:00"));
336         BOOST_CHECK(dcp::LocalTime("2014-01-01T10:00:00+02:00") == dcp::LocalTime("2014-01-01T11:00:00+03:00"));
337 }