xref: /php-src/ext/date/lib/timelib.h (revision 40d06fb6)
1 /*
2  * The MIT License (MIT)
3  *
4  * Copyright (c) 2015-2024 Derick Rethans
5  * Copyright (c) 2018,2021 MongoDB, Inc.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 
26 #ifndef __TIMELIB_H__
27 #define __TIMELIB_H__
28 
29 #ifdef HAVE_TIMELIB_CONFIG_H
30 # include "timelib_config.h"
31 #endif
32 
33 #define TIMELIB_VERSION 202212
34 #define TIMELIB_EXTENDED_VERSION 20221201
35 #define TIMELIB_ASCII_VERSION "2022.12"
36 
37 #include <stdlib.h>
38 #include <stdbool.h>
39 #include <limits.h>
40 #include <inttypes.h>
41 
42 # ifndef HAVE_INT32_T
43 #  if SIZEOF_INT == 4
44 typedef int int32_t;
45 #  elif SIZEOF_LONG == 4
46 typedef long int int32_t;
47 #  endif
48 # endif
49 
50 # ifndef HAVE_UINT32_T
51 #  if SIZEOF_INT == 4
52 typedef unsigned int uint32_t;
53 #  elif SIZEOF_LONG == 4
54 typedef unsigned long int uint32_t;
55 #  endif
56 # endif
57 
58 #ifdef _WIN32
59 # if _MSC_VER >= 1600
60 # include <stdint.h>
61 # endif
62 # ifndef SIZEOF_INT
63 #  define SIZEOF_INT 4
64 # endif
65 # ifndef SIZEOF_LONG
66 #  define SIZEOF_LONG 4
67 # endif
68 # ifndef int32_t
69 typedef __int32           int32_t;
70 # endif
71 # ifndef uint32_t
72 typedef unsigned __int32  uint32_t;
73 # endif
74 # ifndef int64_t
75 typedef __int64           int64_t;
76 # endif
77 # ifndef uint64_t
78 typedef unsigned __int64  uint64_t;
79 # endif
80 # ifndef PRId32
81 #  define PRId32       "I32d"
82 # endif
83 # ifndef PRIu32
84 #  define PRIu32       "I32u"
85 # endif
86 # ifndef PRId64
87 #  define PRId64       "I64d"
88 # endif
89 # ifndef PRIu64
90 #  define PRIu64       "I64u"
91 # endif
92 # ifndef INT32_MAX
93 #define INT32_MAX    _I32_MAX
94 # endif
95 # ifndef INT32_MIN
96 #define INT32_MIN    ((int32_t)_I32_MIN)
97 # endif
98 # ifndef UINT32_MAX
99 #define UINT32_MAX   _UI32_MAX
100 # endif
101 # ifndef INT64_MIN
102 #define INT64_MIN    ((int64_t)_I64_MIN)
103 # endif
104 # ifndef INT64_MAX
105 #define INT64_MAX    _I64_MAX
106 # endif
107 # ifndef UINT64_MAX
108 #define UINT64_MAX   _UI64_MAX
109 # endif
110 #endif
111 
112 #if (defined(__x86_64__) || defined(__LP64__) || defined(_LP64) || defined(_WIN64)) && !defined(TIMELIB_FORCE_LONG32)
113 typedef int64_t timelib_long;
114 typedef uint64_t timelib_ulong;
115 # define TIMELIB_LONG_MAX INT64_MAX
116 # define TIMELIB_LONG_MIN INT64_MIN
117 # define TIMELIB_ULONG_MAX UINT64_MAX
118 # define TIMELIB_LONG_FMT "%" PRId64
119 # define TIMELIB_ULONG_FMT "%" PRIu64
120 #else
121 typedef int32_t timelib_long;
122 typedef uint32_t timelib_ulong;
123 # define TIMELIB_LONG_MAX INT32_MAX
124 # define TIMELIB_LONG_MIN INT32_MIN
125 # define TIMELIB_ULONG_MAX UINT32_MAX
126 # define TIMELIB_LONG_FMT "%" PRId32
127 # define TIMELIB_ULONG_FMT "%" PRIu32
128 #endif
129 
130 #if defined(_MSC_VER)
131 typedef uint64_t timelib_ull;
132 typedef int64_t timelib_sll;
133 # define TIMELIB_LL_CONST(n) n ## i64
134 #else
135 typedef unsigned long long timelib_ull;
136 typedef signed long long timelib_sll;
137 # define TIMELIB_LL_CONST(n) n ## ll
138 #endif
139 
140 typedef struct _ttinfo ttinfo;
141 typedef struct _tlinfo tlinfo;
142 
143 typedef struct _tlocinfo
144 {
145 	char country_code[3];
146 	double latitude;
147 	double longitude;
148 	char *comments;
149 } tlocinfo;
150 
151 #define TIMELIB_POSIX_TRANS_TYPE_JULIAN_NO_FEB29   1
152 #define TIMELIB_POSIX_TRANS_TYPE_JULIAN_FEB29      2
153 #define TIMELIB_POSIX_TRANS_TYPE_MWD               3
154 
155 typedef struct _timelib_posix_trans_info
156 {
157 	int type; // 1=Jn, 2=n, 3=Mm.w.d
158 	union {
159 		int days;
160 		struct {
161 			int month;
162 			int week;
163 			int dow;
164 		} mwd;
165 	};
166 	int hour;
167 } timelib_posix_trans_info;
168 
169 typedef struct _timelib_posix_str
170 {
171 	char        *std;
172 	timelib_sll  std_offset;
173 	char        *dst;
174 	timelib_sll  dst_offset;
175 
176 	timelib_posix_trans_info *dst_begin;
177 	timelib_posix_trans_info *dst_end;
178 
179 	int type_index_std_type;  // index into tz->type
180 	int type_index_dst_type;  // index into tz->type
181 } timelib_posix_str;
182 
183 typedef struct _timelib_posix_transitions {
184 	size_t      count;
185 	timelib_sll times[6];
186 	timelib_sll types[6];
187 } timelib_posix_transitions;
188 
189 typedef struct _timelib_tzinfo
190 {
191 	char    *name;
192 	struct {
193 		uint32_t ttisgmtcnt;
194 		uint32_t ttisstdcnt;
195 		uint32_t leapcnt;
196 		uint32_t timecnt;
197 		uint32_t typecnt;
198 		uint32_t charcnt;
199 	} _bit32;
200 	struct {
201 		uint64_t ttisgmtcnt;
202 		uint64_t ttisstdcnt;
203 		uint64_t leapcnt;
204 		uint64_t timecnt;
205 		uint64_t typecnt;
206 		uint64_t charcnt;
207 	} bit64;
208 
209 	int64_t *trans;
210 	unsigned char *trans_idx;
211 
212 	ttinfo  *type;
213 	char    *timezone_abbr;
214 
215 	tlinfo  *leap_times;
216 	unsigned char bc;
217 	tlocinfo location;
218 
219 	char              *posix_string;
220 	timelib_posix_str *posix_info;
221 } timelib_tzinfo;
222 
223 typedef struct _timelib_rel_time {
224 	timelib_sll y, m, d; /* Years, Months and Days */
225 	timelib_sll h, i, s; /* Hours, mInutes and Seconds */
226 	timelib_sll us;      /* Microseconds */
227 
228 	int weekday; /* Stores the day in 'next monday' */
229 	int weekday_behavior; /* 0: the current day should *not* be counted when advancing forwards; 1: the current day *should* be counted */
230 
231 	int first_last_day_of;
232 	int invert; /* Whether the difference should be inverted */
233 	timelib_sll days; /* Contains the number of *days*, instead of Y-M-D differences */
234 
235 	struct {
236 		unsigned int type;
237 		timelib_sll amount;
238 	} special;
239 
240 	unsigned int   have_weekday_relative, have_special_relative;
241 } timelib_rel_time;
242 
243 typedef struct _timelib_time_offset {
244 	int32_t      offset;
245 	unsigned int leap_secs;
246 	unsigned int is_dst;
247 	char        *abbr;
248 	timelib_sll  transition_time;
249 } timelib_time_offset;
250 
251 typedef struct _timelib_time {
252 	timelib_sll      y, m, d;     /* Year, Month, Day */
253 	timelib_sll      h, i, s;     /* Hour, mInute, Second */
254 	timelib_sll      us;          /* Microseconds */
255 	int              z;           /* UTC offset in seconds */
256 	char            *tz_abbr;     /* Timezone abbreviation (display only) */
257 	timelib_tzinfo  *tz_info;     /* Timezone structure */
258 	signed int       dst;         /* Flag if we were parsing a DST zone */
259 	timelib_rel_time relative;
260 
261 	timelib_sll      sse;         /* Seconds since epoch */
262 
263 	unsigned int   have_time, have_date, have_zone, have_relative, have_weeknr_day;
264 
265 	unsigned int   sse_uptodate; /* !0 if the sse member is up to date with the date/time members */
266 	unsigned int   tim_uptodate; /* !0 if the date/time members are up to date with the sse member */
267 	unsigned int   is_localtime; /*  1 if the current struct represents localtime, 0 if it is in GMT */
268 	unsigned int   zone_type;    /*  1 time offset,
269 	                              *  3 TimeZone identifier,
270 	                              *  2 TimeZone abbreviation */
271 } timelib_time;
272 
273 typedef struct _timelib_abbr_info {
274 	timelib_sll  utc_offset;
275 	char        *abbr;
276 	int          dst;
277 } timelib_abbr_info;
278 
279 #define TIMELIB_WARN_MASK                      0x1ff
280 #define TIMELIB_ERR_MASK                       0x2ff
281 
282 #define TIMELIB_WARN_DOUBLE_TZ                 0x101
283 #define TIMELIB_WARN_INVALID_TIME              0x102
284 #define TIMELIB_WARN_INVALID_DATE              0x103
285 #define TIMELIB_WARN_TRAILING_DATA             0x11a
286 
287 #define TIMELIB_ERR_DOUBLE_TZ                  0x201
288 #define TIMELIB_ERR_TZID_NOT_FOUND             0x202
289 #define TIMELIB_ERR_DOUBLE_TIME                0x203
290 #define TIMELIB_ERR_DOUBLE_DATE                0x204
291 #define TIMELIB_ERR_UNEXPECTED_CHARACTER       0x205
292 #define TIMELIB_ERR_EMPTY_STRING               0x206
293 #define TIMELIB_ERR_UNEXPECTED_DATA            0x207
294 #define TIMELIB_ERR_NO_TEXTUAL_DAY             0x208
295 #define TIMELIB_ERR_NO_TWO_DIGIT_DAY           0x209
296 #define TIMELIB_ERR_NO_THREE_DIGIT_DAY_OF_YEAR 0x20a
297 #define TIMELIB_ERR_NO_TWO_DIGIT_MONTH         0x20b
298 #define TIMELIB_ERR_NO_TEXTUAL_MONTH           0x20c
299 #define TIMELIB_ERR_NO_TWO_DIGIT_YEAR          0x20d
300 #define TIMELIB_ERR_NO_FOUR_DIGIT_YEAR         0x20e
301 #define TIMELIB_ERR_NO_TWO_DIGIT_HOUR          0x20f
302 #define TIMELIB_ERR_HOUR_LARGER_THAN_12        0x210
303 #define TIMELIB_ERR_MERIDIAN_BEFORE_HOUR       0x211
304 #define TIMELIB_ERR_NO_MERIDIAN                0x212
305 #define TIMELIB_ERR_NO_TWO_DIGIT_MINUTE        0x213
306 #define TIMELIB_ERR_NO_TWO_DIGIT_SECOND        0x214
307 #define TIMELIB_ERR_NO_SIX_DIGIT_MICROSECOND   0x215
308 #define TIMELIB_ERR_NO_SEP_SYMBOL              0x216
309 #define TIMELIB_ERR_EXPECTED_ESCAPE_CHAR       0x217
310 #define TIMELIB_ERR_NO_ESCAPED_CHAR            0x218
311 #define TIMELIB_ERR_WRONG_FORMAT_SEP           0x219
312 #define TIMELIB_ERR_TRAILING_DATA              0x21a
313 #define TIMELIB_ERR_DATA_MISSING               0x21b
314 #define TIMELIB_ERR_NO_THREE_DIGIT_MILLISECOND 0x21c
315 #define TIMELIB_ERR_NO_FOUR_DIGIT_YEAR_ISO     0x21d
316 #define TIMELIB_ERR_NO_TWO_DIGIT_WEEK          0x21e
317 #define TIMELIB_ERR_INVALID_WEEK               0x21f
318 #define TIMELIB_ERR_NO_DAY_OF_WEEK             0x220
319 #define TIMELIB_ERR_INVALID_DAY_OF_WEEK        0x221
320 #define TIMELIB_ERR_INVALID_SPECIFIER          0x222
321 #define TIMELIB_ERR_INVALID_TZ_OFFSET          0x223
322 #define TIMELIB_ERR_FORMAT_LITERAL_MISMATCH    0x224
323 #define TIMELIB_ERR_MIX_ISO_WITH_NATURAL       0x225
324 #define TIMELIB_ERR_NUMBER_OUT_OF_RANGE        0x226
325 
326 #define TIMELIB_ZONETYPE_NONE   0
327 #define TIMELIB_ZONETYPE_OFFSET 1
328 #define TIMELIB_ZONETYPE_ABBR   2
329 #define TIMELIB_ZONETYPE_ID     3
330 
331 typedef struct _timelib_error_message {
332 	int         error_code;
333 	int         position;
334 	char        character;
335 	char       *message;
336 } timelib_error_message;
337 
338 typedef struct _timelib_error_container {
339 	timelib_error_message *error_messages;
340 	timelib_error_message *warning_messages;
341 	int                    error_count;
342 	int                    warning_count;
343 } timelib_error_container;
344 
345 typedef struct _timelib_tz_lookup_table {
346 	const char *name;
347 	int         type;
348 	float       gmtoffset;
349 	const char *full_tz_name;
350 } timelib_tz_lookup_table;
351 
352 typedef struct _timelib_tzdb_index_entry {
353 	char *id;
354 	unsigned int pos;
355 } timelib_tzdb_index_entry;
356 
357 typedef struct _timelib_tzdb {
358 	const char                     *version;
359 	int                             index_size;
360 	const timelib_tzdb_index_entry *index;
361 	const unsigned char            *data;
362 } timelib_tzdb;
363 
364 #ifndef timelib_malloc
365 # define timelib_malloc  malloc
366 # define timelib_realloc realloc
367 # define timelib_calloc  calloc
368 # define timelib_strdup  strdup
369 # define timelib_free    free
370 # if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
371 #  define TIMELIB_USE_BUILTIN_STRNDUP 1
372 # else
373 #  define TIMELIB_USE_BUILTIN_STRNDUP 0
374 #  define timelib_strndup strndup
375 # endif
376 #endif
377 
378 #define TIMELIB_NONE             0x00
379 #define TIMELIB_OVERRIDE_TIME    0x01
380 #define TIMELIB_NO_CLONE         0x02
381 
382 #define TIMELIB_UNSET   -9999999
383 
384 /* An entry for each of these error codes is also in the
385  * timelib_error_messages array in timelib.c.
386  * Codes 0x00, 0x07, and 0x09 are warnings only. */
387 #define TIMELIB_ERROR_NO_ERROR                            0x00
388 #define TIMELIB_ERROR_CANNOT_ALLOCATE                     0x01
389 #define TIMELIB_ERROR_CORRUPT_TRANSITIONS_DONT_INCREASE   0x02
390 #define TIMELIB_ERROR_CORRUPT_NO_64BIT_PREAMBLE           0x03
391 #define TIMELIB_ERROR_CORRUPT_NO_ABBREVIATION             0x04
392 #define TIMELIB_ERROR_UNSUPPORTED_VERSION                 0x05
393 #define TIMELIB_ERROR_NO_SUCH_TIMEZONE                    0x06
394 #define TIMELIB_ERROR_SLIM_FILE                           0x07 /* Warns if the file is SLIM, but we can't read it */
395 #define TIMELIB_ERROR_CORRUPT_POSIX_STRING                0x08
396 #define TIMELIB_ERROR_EMPTY_POSIX_STRING                  0x09 /* Warns if the POSIX string is empty, but still produces results */
397 
398 #ifdef __cplusplus
399 extern "C" {
400 #endif
401 
402 typedef enum _timelib_format_specifier_code {
403 	TIMELIB_FORMAT_ALLOW_EXTRA_CHARACTERS = 0,
404 	TIMELIB_FORMAT_ANY_SEPARATOR,
405 	TIMELIB_FORMAT_DAY_TWO_DIGIT,
406 	TIMELIB_FORMAT_DAY_TWO_DIGIT_PADDED,
407 	TIMELIB_FORMAT_DAY_OF_WEEK_ISO,
408 	TIMELIB_FORMAT_DAY_OF_WEEK,
409 	TIMELIB_FORMAT_DAY_OF_YEAR,
410 	TIMELIB_FORMAT_DAY_SUFFIX,
411 	TIMELIB_FORMAT_END,
412 	TIMELIB_FORMAT_EPOCH_SECONDS,
413 	TIMELIB_FORMAT_ESCAPE,
414 	TIMELIB_FORMAT_HOUR_TWO_DIGIT_12_MAX,
415 	TIMELIB_FORMAT_HOUR_TWO_DIGIT_12_MAX_PADDED,
416 	TIMELIB_FORMAT_HOUR_TWO_DIGIT_24_MAX,
417 	TIMELIB_FORMAT_HOUR_TWO_DIGIT_24_MAX_PADDED,
418 	TIMELIB_FORMAT_LITERAL,
419 	TIMELIB_FORMAT_MERIDIAN,
420 	TIMELIB_FORMAT_MICROSECOND_SIX_DIGIT,
421 	TIMELIB_FORMAT_MILLISECOND_THREE_DIGIT,
422 	TIMELIB_FORMAT_MINUTE_TWO_DIGIT,
423 	TIMELIB_FORMAT_MONTH_TWO_DIGIT,
424 	TIMELIB_FORMAT_MONTH_TWO_DIGIT_PADDED,
425 	TIMELIB_FORMAT_RANDOM_CHAR,
426 	TIMELIB_FORMAT_RESET_ALL,
427 	TIMELIB_FORMAT_RESET_ALL_WHEN_NOT_SET,
428 	TIMELIB_FORMAT_SECOND_TWO_DIGIT,
429 	TIMELIB_FORMAT_SEPARATOR,
430 	TIMELIB_FORMAT_SKIP_TO_SEPARATOR,
431 	TIMELIB_FORMAT_TEXTUAL_DAY_3_LETTER,
432 	TIMELIB_FORMAT_TEXTUAL_DAY_FULL,
433 	TIMELIB_FORMAT_TEXTUAL_MONTH_3_LETTER,
434 	TIMELIB_FORMAT_TEXTUAL_MONTH_FULL,
435 	TIMELIB_FORMAT_TIMEZONE_OFFSET,
436 	TIMELIB_FORMAT_TIMEZONE_OFFSET_MINUTES,
437 	TIMELIB_FORMAT_WEEK_OF_YEAR_ISO,
438 	TIMELIB_FORMAT_WEEK_OF_YEAR,
439 	TIMELIB_FORMAT_WHITESPACE,
440 	TIMELIB_FORMAT_YEAR_TWO_DIGIT,
441 	TIMELIB_FORMAT_YEAR_FOUR_DIGIT,
442 	TIMELIB_FORMAT_YEAR_EXPANDED,
443 	TIMELIB_FORMAT_YEAR_ISO
444 } timelib_format_specifier_code;
445 
446 typedef struct _timelib_format_specifier {
447 	char                          specifier;
448 	timelib_format_specifier_code code;
449 } timelib_format_specifier;
450 
451 typedef struct _timelib_format_config {
452 	const timelib_format_specifier *format_map;
453 	/* Format speciifiers must be preceded by 'prefix_char' if not '\0'. */
454 	char                            prefix_char;
455 } timelib_format_config;
456 
457 /* Function pointers */
458 typedef timelib_tzinfo* (*timelib_tz_get_wrapper)(const char *tzname, const timelib_tzdb *tzdb, int *error_code);
459 
460 /* From dow.c */
461 /* Calculates the day of the week from y, m, and d. 0=Sunday..6=Saturday */
462 timelib_sll timelib_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d);
463 
464 /* Calculates the day of the ISO week from y, m, and d. 1=Monday, 7=Sunday */
465 timelib_sll timelib_iso_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d);
466 
467 /* Calculates the day of the year according to y-m-d. 0=Jan 1st..364/365=Dec
468  * 31st */
469 timelib_sll timelib_day_of_year(timelib_sll y, timelib_sll m, timelib_sll d);
470 
471 /* Calculates the day of the year according to y-w-dow. 0..364/365 */
472 timelib_sll timelib_daynr_from_weeknr(timelib_sll iy, timelib_sll iw, timelib_sll id);
473 
474 /* Calculates the number of days in month m for year y. 28..31 */
475 timelib_sll timelib_days_in_month(timelib_sll y, timelib_sll m);
476 
477 /* Calculates the ISO year and week from y, m, and d, into iw and iy */
478 void timelib_isoweek_from_date(timelib_sll y, timelib_sll m, timelib_sll d, timelib_sll *iw, timelib_sll *iy);
479 
480 /* Calculates the ISO year, week, and day of week from y, m, and d, into iy,
481  * iw, and id */
482 void timelib_isodate_from_date(timelib_sll y, timelib_sll m, timelib_sll d, timelib_sll *iy, timelib_sll *iw, timelib_sll *id);
483 
484 /* Calculates the year, month, and day from iy, iw, and iw, into y, m, and d */
485 void timelib_date_from_isodate(timelib_sll iy, timelib_sll iw, timelib_sll id, timelib_sll *y, timelib_sll *m, timelib_sll *d);
486 
487 /* Returns true if h, i and s fit in the range 00:00:00..23:59:59, false
488  * otherwise */
489 int timelib_valid_time(timelib_sll h, timelib_sll i, timelib_sll s);
490 
491 /* Returns true if m fits in the range 1..12, and d fits in the range
492  * 1..<days-in-month> for year y */
493 int timelib_valid_date(timelib_sll y, timelib_sll m, timelib_sll d);
494 
495 /* From parse_date.re */
496 
497 /* Parses the date/time string in 's' with length 'len' into the constituent
498  * parts of timelib_time*.
499  *
500  * Depending on the contents of the string 's', not all elements might be
501  * filled. You can check whether a specific element has been parsed by
502  * comparing with the TIMELIB_UNSET define.
503  *
504  * If errors occur, this function keeps already parsed elements in the
505  * returned timelib_time* value.
506  *
507  * If the **errors points to a timelib_error_container variable, warnings
508  * and errors will be recorded. You are responsible for freeing the stored
509  * information with timelib_error_container_dtor(). To see whether errors have
510  * occurred, inspect errors->errors_count. To see whether warnings have occurred,
511  * inspect errors->warnings_count.
512  *
513  * The returned timelib_time* value is dynamically allocated and should be
514  * freed with timelib_time_dtor().
515  */
516 timelib_time *timelib_strtotime(const char *s, size_t len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper);
517 
518 /* Parses the date/time string in 's' with length 'len' into the constituent
519  * parts of timelib_time* according to the format in 'format'.
520  *
521  * Depending on the contents of the string 's', not all elements might be
522  * filled. You can check whether a specific element has been parsed by
523  * comparing with the TIMELIB_UNSET define.
524  *
525  * If errors occur, this function keeps already parsed elements in the
526  * returned timelib_time* value.
527  *
528  * If the **errors points to a timelib_error_container variable, warnings
529  * and errors will be recorded. You are responsible for freeing the stored
530  * information with timelib_error_container_dtor(). To see whether errors have
531  * occurred, inspect errors->errors_count. To see whether warnings have occurred,
532  * inspect errors->warnings_count.
533  *
534  * The returned timelib_time* value is dynamically allocated and should be
535  * freed with timelib_time_dtor().
536  */
537 timelib_time *timelib_parse_from_format(const char *format, const char *s, size_t len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper);
538 
539 /* Parses the date/time string in 's' with length 'len' into the constituent
540  * parts of timelib_time* according to the format in 'format' with format
541  * specifier configuration 'format_config'.
542  *
543  * 'format_map' is an array of pairs, with the first element being the format
544  * specifier as a character and the second element corresponds to the
545  * representation of the specifier from the enum list
546  * 'timelib_format_specifier_code'.
547  *
548  * Note: 'format_map' must be terminated with specifier '\0' to indicate to the
549  * parser that there are no more format specifiers in the list.
550  */
551 timelib_time *timelib_parse_from_format_with_map(const char *format, const char *s, size_t len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper, const timelib_format_config* format_config);
552 
553 /* Fills the gaps in the parsed timelib_time with information from the reference date/time in 'now'
554  *
555  * If any of the 'parsed' y, m, d, h, i or s parameters is unset (TIMELIB_UNSET):
556  * - if microtime (us) is unset, then the us of the parsed time is set to 0.
557  * - else if microtime (us) is unset and 'now'->'us' is set, use it, otherwise use 0.
558  *
559  * For either of the 'parsed' y, m, d, h, i, s, z (utc offset in seconds) or
560  * dst is unset, set it to the corresponding value in 'now' if set, otherwise
561  * set it to 0.
562  *
563  * It duplicates tz_abbr if unset in 'parsed' but set in 'now'.
564  *
565  * It duplicates tz_info if unset in 'parsed', but set in 'now' unless
566  * TIMELIB_NO_CLONE is passed, in which case only the pointer in 'parsed' is
567  * set to 'now'.
568  *
569  * If the option TIMELIB_OVERRIDE_TIME is passed and the parsed date/time has
570  * no time portion, the function will ignore the time aspect in 'now' and
571  * instead fill it with zeros.
572  */
573 void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options);
574 
575 /* Tries to convert a time zone abbreviation, gmtoffset and/or isdst flag
576  * combination to a time zone identifier.
577  *
578  * If 'abbr' is either 'utc' or 'gmt' (case insensitve) then "UTC" is
579  * returned.
580  *
581  * It first uses the data in the timezonemap.h file to find a matching
582  * abbreviation/GMT offset combination. If not found, it uses the data in
583  * fallbackmap.h to match only the GMT offset/isdst flag to try to find a
584  * match. If nothing is found, NULL is returned.
585  *
586  * The returned char* is not duplicated, and should not be freed.
587  */
588 const char *timelib_timezone_id_from_abbr(const char *abbr, timelib_long gmtoffset, int isdst);
589 
590 /* Returns an array of known time zone abbreviations
591  *
592  * This file is generated from the time zone database through the
593  * gettzmapping.php scripts, which requires that an up-to-date time zone
594  * database is used with the PHP binary that runs the script.
595  *
596  * Each item in the returned list contains the abbreviation, a flag whether
597  * it's an abbreviation used with DST, the UTC offset in seconds, and the name
598  * of the time zone identifier that this abbreviation belongs to.
599  *
600  * The order for each specific abbreviation is controlled through the
601  * preference list in the gettzmapping.php script. Time zones that match the
602  * pattern ±\d{2,4} are excluded
603  */
604 const timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void);
605 
606 /**
607  * DEPRECATED, but still used by PHP.
608  */
609 timelib_long timelib_parse_zone(const char **ptr, int *dst, timelib_time *t, int *tz_not_found, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_wrapper);
610 
611 /* From parse_iso_intervals.re */
612 
613 /**
614  * Parses a subset of an ISO 8601 intervals specification string into its
615  * constituent parts.
616  *
617  * If the **errors points to a timelib_error_container variable, warnings
618  * and errors will be recorded. You are responsible for freeing the stored
619  * information with timelib_error_container_dtor(). To see whether errors have
620  * occurred, inspect errors->errors_count. To see whether warnings have occurred,
621  * inspect errors->warnings_count.
622  */
623 void timelib_strtointerval(const char *s, size_t len,
624                            timelib_time **begin, timelib_time **end,
625                            timelib_rel_time **period, int *recurrences,
626                            timelib_error_container **errors);
627 
628 
629 /* From tm2unixtime.c */
630 
631 /**
632  * Uses the y/m/d/h/i/s fields to calculate and store the equivalent timestamp
633  * in the sse field.
634  *
635  * It uses the time zone information associated with 'time' to account for the
636  * right UTC offset and/or DST rules. You can associate time zone information
637  * with the timelib_set_timezone_* functions (see below).
638  *
639  * If the type is 'TIMELIB_ZONETYPE_ID' and there is no associated tzinfo, it
640  * will use the second argument 'tzi' to provide the rules necessary to
641  * calculate the right timestamp.
642  */
643 void timelib_update_ts(timelib_time* time, timelib_tzinfo* tzi);
644 
645 /**
646  * Returns the number of days from the y/m/d fields of 'time' since the Unix
647  * Epoch.
648  */
649 timelib_sll timelib_epoch_days_from_time(timelib_time *time);
650 
651 /**
652  * Takes the information from the y/m/d/h/i/s fields and makes sure their
653  * values are in the right range.
654  *
655  * If a value under- or overflows it will adjust the larger measure up (or
656  * down). It also takes into account leap days.
657  */
658 void timelib_do_normalize(timelib_time *base);
659 
660 /**
661  * Takes the information from the y/m/d/h/i/s fields of 'rt' and makes sure
662  * their values are in the right range.
663  *
664  * If a value under- or overflows it will adjust the larger measure up (or
665  * down). As this function operates on a *relative date/time*, it also takes
666  * into account leap days and correctly accounts for the difference depending
667  * on the base date/time in 'base'.
668  */
669 void timelib_do_rel_normalize(timelib_time *base, timelib_rel_time *rt);
670 
671 /* From unixtime2tm.c */
672 
673 /**
674  * Takes the unix timestamp in seconds from 'ts', and calculates y, m, and d,
675  * in the proleptic Gregorian calendar.
676  *
677  * It uses the algorithm from howardhinnant.github.io/date_algorithms.html
678  */
679 void timelib_unixtime2date(timelib_sll ts, timelib_sll *y, timelib_sll *m, timelib_sll *d);
680 
681 /**
682  * Takes the unix timestamp in seconds from 'ts' and populates the y/m/d/h/i/s
683  * fields of 'tm' without taking time zones into account
684  */
685 void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts);
686 
687 /**
688  * Takes the Unix timestamp from 'ts', and calculates the y/m/d/h/i/s fields
689  * according to the time zone information attached to 'tm'.
690  */
691 void timelib_unixtime2local(timelib_time *tm, timelib_sll ts);
692 
693 /**
694  * Takes the Unix timestamp stored in 'tm', and calculates the y/m/d/h/i/s
695  * fields according to the time zone information attached to 'tm'.
696  */
697 void timelib_update_from_sse(timelib_time *tm);
698 
699 /**
700  * Attaches the UTC offset as time zone information to 't'.
701  *
702  * 'utc_offset' is in seconds East of UTC.
703  */
704 void timelib_set_timezone_from_offset(timelib_time *t, timelib_sll utc_offset);
705 
706 /**
707  * Attaches the information from 'abbr_info' as time zone information to 't'.
708  *
709  * The timelib_abbr_info struct contains an abbreviation ('abbr') which string
710  * value is duplicated, as well as a 'utc_offset' and 'dst' flag. It only
711  * supports a 'dst' change over of 1 hour.
712  */
713 void timelib_set_timezone_from_abbr(timelib_time *t, timelib_abbr_info abbr_info);
714 
715 /**
716  * Attaches the time zone information in 'tz' to to 't'.
717  *
718  * It fetches the right UTC offset that is currently stored in the time
719  * stamp field in 't' ('sse'), and assigns that to the 'z' field and 'dst'
720  * field (whether DST is in effect at the time). It also sets the current
721  * abbreviation to the 'tz_addr' field, making sure that if a value was already
722  * set it was freed.
723  *
724  * The time zone information in 'tz' is *not* duplicated into the 't' field so
725  * it should not be freed until all timelib_time* variables have been freed as
726  * well.
727  */
728 void timelib_set_timezone(timelib_time *t, timelib_tzinfo *tz);
729 
730 /* From parse_tz.c */
731 
732 /**
733  * Returns whether the time zone ID 'timezone' is available in the time zone
734  * database as pointed to be 'tzdb'.
735  */
736 int timelib_timezone_id_is_valid(const char *timezone, const timelib_tzdb *tzdb);
737 
738 /**
739  * Converts the binary stored time zone information from 'tzdb' for the time
740  * zone 'timezone' into a structure the library can use for calculations.
741  *
742  * The function can be used on both timelib_builtin_db as well as a time zone
743  * db as opened by timelib_zoneinfo.
744  *
745  * 'error_code' must not be a null pointer, and will always be written to. If
746  * the value is TIMELIB_ERROR_NO_ERROR then the file was parsed without
747  * problems.
748  *
749  * The function will return null upon failure, and also set an error code
750  * through 'error_code'.
751  *
752  * The error code is one of the TIMELIB_ERROR_* constants as listed above.
753  * These error constants can be converted into a string by
754  * timelib_get_error_message.
755  *
756  * If the function returns not-null, the 'error_code' might have a non-null
757  * value that can be used to detect incompatibilities. The only one that is
758  * currently detected is whether the file is a 'slim' file, in which case
759  * 'error_code' will be set to TIMELIB_ERROR_SLIM_FILE.
760  *
761  * This function allocates memory for the new time zone structure, which must
762  * be freed after use. Although it is recommended that a cache of each used
763  * time zone is kept.
764  */
765 timelib_tzinfo *timelib_parse_tzfile(const char *timezone, const timelib_tzdb *tzdb, int *error_code);
766 
767 /**
768  * Frees up the resources allocated by 'timelib_parse_tzfile'.
769  */
770 void timelib_tzinfo_dtor(timelib_tzinfo *tz);
771 
772 /**
773  * Deep-clones a timelib_tzinfo structure.
774  *
775  * This allocates resources that need to be freed with 'timelib_tzinfo_dtor'
776  */
777 timelib_tzinfo* timelib_tzinfo_clone(timelib_tzinfo *tz);
778 
779 /**
780  * Returns whether DST is active with time zone 'tz' for the time stamp 'ts'.
781  *
782  * Returns 0 if DST is not active, 1 if DST is active, or -1 if no transitions
783  * were available through 'tz'.
784  */
785 int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz);
786 
787 /**
788  * Returns offset information with time zone 'tz' for the time stamp 'ts'.
789  *
790  * The returned information contains: the offset in seconds East of UTC (in
791  * 'offset'), whether DST is active ('is_dst'), what the current time zone
792  * abbreviation is ('abbr') and the transition time that got to this state (in
793  * 'transition_time');
794  */
795 timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz);
796 
797 /**
798  * Returns offset information with time zone 'tz' for the time stamp 'ts'.
799  *
800  * The returned information contains: the offset in seconds East of UTC (in
801  * the output parameter 'offset'), whether DST is active (in the output
802  * parameter 'is_dst'), and the transition time that got to this state (in
803  * the output parameter 'transition_time'); if NULL is passed, the value is
804  * not retrieved
805  *
806  * Returns 1 if successful, 0 for failure.
807  */
808 int timelib_get_time_zone_offset_info(timelib_sll ts, timelib_tzinfo *tz, int32_t* offset, timelib_sll* transition_time, unsigned int* is_dst);
809 
810 /**
811  * Returns the UTC offset currently applicable for the information stored in 't'.
812  *
813  * The value returned is the UTC offset in seconds East.
814  */
815 timelib_sll timelib_get_current_offset(timelib_time *t);
816 
817 /**
818  * Returns whether the timezone information in *one and *two are the same
819  *
820  * A timezone is considered the same if:
821  * - the ->zone_type values are the same for *one and *two
822  * - for TYPE_ABBR and TYPE_OFFSET, ->z + (->dst * 3600), is the same
823  * - for TYPE_ID, the zone's names are the same
824  */
825 int timelib_same_timezone(timelib_time *one, timelib_time *two);
826 
827 /**
828  * Displays debugging information about the time zone information in 'tz'.
829  */
830 void timelib_dump_tzinfo(timelib_tzinfo *tz);
831 
832 /**
833  * Returns a pointer to the built-in time zone database.
834  *
835  * You must *not* free the returned pointer as it is part of the text segment.
836  */
837 const timelib_tzdb *timelib_builtin_db(void);
838 
839 /**
840  * Returns a pointer to the start of an array containing a list of timezone identifiers.
841  *
842  * The amount of entries in the array is returned through the 'count' OUT parameter.
843  *
844  * Each entry contains the time zone ID ('id' field), and the position within the time zone
845  * information ('pos' field). The pos field should not be used.
846  */
847 const timelib_tzdb_index_entry *timelib_timezone_identifiers_list(const timelib_tzdb *tzdb, int *count);
848 
849 /* From parse_zoneinfo.c */
850 
851 /**
852  * Scans the directory and subdirectories of 'directory' for valid time zone files and builds
853  * a time zone database out of these files.
854  *
855  * Typically, the directory should point to '/usr/share/zoneinfo'.
856  *
857  * Unlike 'timelib_builtin_db', the return value of this function must be freed
858  * with the 'timelib_zoneinfo_dtor' function.
859  */
860 timelib_tzdb *timelib_zoneinfo(const char *directory);
861 
862 /**
863  * Frees up the resources as created through 'timelib_zoneinfo'.
864  *
865  * This function must be used to free up all the resources that have been
866  * allocated while calling 'timelib_zoneinfo'.
867  */
868 void timelib_zoneinfo_dtor(timelib_tzdb *tzdb);
869 
870 /* From timelib.c */
871 
872 /**
873  * Returns a static string containing an error message belonging to a specific
874  * error code.
875  */
876 const char *timelib_get_error_message(int error_code);
877 
878 /**
879  * Allocates resources for the relative time structure.
880  *
881  * Must be freed with 'timelib_rel_time_dtor'.
882  */
883 timelib_rel_time* timelib_rel_time_ctor(void);
884 
885 /**
886  * Frees up the resources as allocated through 'timelib_rel_time_ctor'.
887  */
888 void timelib_rel_time_dtor(timelib_rel_time* t);
889 
890 /**
891  * Creates a new timelib_rel_time resource and copies over the information
892  * from 'tz'.
893  *
894  * Must be freed with 'timelib_rel_time_dtor'.
895  */
896 timelib_rel_time* timelib_rel_time_clone(timelib_rel_time *tz);
897 
898 /**
899  * Allocates resources for the time structure.
900  *
901  * Must be freed with 'timelib_time_dtor'.
902  */
903 timelib_time* timelib_time_ctor(void);
904 
905 /**
906  * Frees up the resources as allocated through 'timelib_time_ctor'.
907  */
908 void timelib_time_dtor(timelib_time* t);
909 
910 /**
911  * Creates a new timelib_time resource and copies over the information
912  * from 'orig'.
913  *
914  * Must be freed with 'timelib_time_dtor'.
915  */
916 timelib_time* timelib_time_clone(timelib_time* orig);
917 
918 /**
919  * Compares two timelib_time structures and returns which one is earlier in
920  * time.
921  *
922  * To decide which comes earlier it uses the 'sse' (Seconds Since Epoch) and
923  * 'us' (microseconds) fields.
924  *
925  * Returns -1 if t1 < t2, 0 if t1 == t2, and -1 if t1 > t2.
926  */
927 int timelib_time_compare(timelib_time *t1, timelib_time *t2);
928 
929 /**
930  * Allocates resources for the time offset structure.
931  *
932  * Must be freed with 'timelib_time_offset_dtor'.
933  */
934 timelib_time_offset* timelib_time_offset_ctor(void);
935 
936 /**
937  * Frees up the resources as allocated through 'timelib_time_offset_ctor'.
938  */
939 void timelib_time_offset_dtor(timelib_time_offset* t);
940 
941 /**
942  * Frees up the resources allocated while converting strings to timelib_time
943  * structures with the timelib_strtotime and timelib_strtointerval functions.
944  */
945 void timelib_error_container_dtor(timelib_error_container *errors);
946 
947 /**
948  * Converts the 'sse' value of 'd' to a timelib_long type.
949  *
950  * If the value fits in the TIMELIB_LONG_MIN and TIMELIB_LONG_MAX range, the
951  * value is cast to (timelib_long) and returned. If *error is not a NULL
952  * pointer, it will be set to 0.
953  *
954  * If the value does *not* fit in the range, the function returns 0 and if
955  * *error is not a NULL pointer, it will be set to 1.
956  *
957  * timelib_long is a 32 bit signed long integer on 32 bit platforms, and a 64
958  * bit signed long long integer on 64 bit platforms. In other words, it makes
959  * sure that the value in 'sse' (which is always a signed long long 64 bit
960  * integer) can be used safely outside of the library.
961  */
962 timelib_long timelib_date_to_int(timelib_time *d, int *error);
963 
964 /**
965  * Displays debugging information about the date/time information stored in 'd'.
966  *
967  * 'options' is a bit field, where:
968  * - 1 controls whether the relative time portion is shown.
969  * - 2 controls whether the zone type is shown.
970  */
971 void timelib_dump_date(timelib_time *d, int options);
972 
973 /**
974  * Displays debugging information about the relative time information stored
975  * in 'd'.
976  */
977 void timelib_dump_rel_time(timelib_rel_time *d);
978 
979 /**
980  * Converts a decimal hour into hour/min/sec components
981  */
982 void timelib_decimal_hour_to_hms(double h, int *hour, int *min, int *sec);
983 
984 /**
985  * Converts hour/min/sec values into a decimal hour
986  */
987 void timelib_hms_to_decimal_hour(int hour, int min, int sec, double *h);
988 
989 /**
990  * Converts hour/min/sec/micro sec values into a decimal hour
991  */
992 void timelib_hmsf_to_decimal_hour(int hour, int min, int sec, int us, double *h);
993 
994 /**
995  * Converts hour/min/sec values into seconds
996  */
997 timelib_sll timelib_hms_to_seconds(timelib_sll h, timelib_sll m, timelib_sll s);
998 
999 
1000 /* from astro.c */
1001 
1002 /**
1003  * Converts the Unix Epoch time stamp 'ts' to a Julian Day
1004  *
1005  * The value returned is the number of whole days since -4714-11-24T12:00:00 UTC
1006  * (in the proleptic Gregorian calendar):
1007  * https://en.wikipedia.org/wiki/Julian_day
1008  */
1009 double timelib_ts_to_julianday(timelib_sll ts);
1010 
1011 /**
1012  * Converts the Unix Epoch time stamp 'ts' to the J2000 epoch
1013  *
1014  * The value returned is the number of whole days since 2000-01-01T12:00:00
1015  * UTC: https://en.wikipedia.org/wiki/Epoch_(astronomy)#Julian_years_and_J2000
1016  */
1017 double timelib_ts_to_j2000(timelib_sll ts);
1018 
1019 /**
1020  * Calculates when the Sun is above a certain latitude.
1021  *
1022  * Parameters:
1023  * - time: A timelib_time time describing that needs to specific midnight for a
1024  *         specific day.
1025  * - lon: The longitude of the observer (East positive, West negative).
1026  * - lat: The latitude of the observer (North positive, South negative).
1027  * - altit: The altitude. Set to -35/60 for rise/set, -6 for civil twilight,
1028  *          -12 for nautical, and -18 for astronomical twilight.
1029  * - upper_limb: set to non-zero for rise/set calculations, and 0 for twilight
1030  *               calculations.
1031  *
1032  * Out Parameters:
1033  * - h_rise: The decimal hour when the Sun rises
1034  * - h_set: The decimal hour when the Sun sets
1035  * - ts_rise: The Unix timestamp of the Sun rising
1036  * - ts_set: The Unix timestamp of the Sun setting
1037  * - ts_transit: The Unix timestmap of the Sun transitting through South
1038  *
1039  * Return Values:
1040  * - 0: The Sun rises and sets.
1041  * - +1: The Sun is always above the horizon. (ts_rise is set to ts_transit -
1042  *       (12 * 3600); ts_set is set to ts_transit + (12 * 3600).
1043  * - -1: The Sun is awlays below the horizon. (ts_rise and ts_set are set
1044  *       to ts_transit)
1045  */
1046 int timelib_astro_rise_set_altitude(timelib_time *time, double lon, double lat, double altit, int upper_limb, double *h_rise, double *h_set, timelib_sll *ts_rise, timelib_sll *ts_set, timelib_sll *ts_transit);
1047 
1048 /* from interval.c */
1049 
1050 /**
1051  * Calculates the difference between two times
1052  *
1053  * The result is a timelib_rel_time structure that describes how you can
1054  * convert from 'one' to 'two' with 'timelib_add'. This does *not* necessarily
1055  * mean that you can go from 'two' to 'one' by using 'timelib_sub' due to the
1056  * way months and days are calculated.
1057  */
1058 timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two);
1059 
1060 /**
1061  * Calculates the difference in full days between two times
1062  *
1063  * The result is the number of full days between 'one' and 'two'. It does take
1064  * into account 23 and 25 hour (and variants) days when the zone_type
1065  * is TIMELIB_ZONETYPE_ID and have the same TZID for 'one' and 'two'.
1066  */
1067 int timelib_diff_days(timelib_time *one, timelib_time *two);
1068 
1069 /**
1070  * Adds the relative time information 'interval' to the base time 't'.
1071  *
1072  * This can be a relative time as created by 'timelib_diff', but also by more
1073  * complex statements such as "next workday".
1074  */
1075 timelib_time *timelib_add(timelib_time *t, timelib_rel_time *interval);
1076 timelib_time *timelib_add_wall(timelib_time *t, timelib_rel_time *interval);
1077 
1078 /**
1079  * Subtracts the relative time information 'interval' to the base time 't'.
1080  *
1081  * This can be a relative time as created by 'timelib_diff'. Unlike with
1082  * 'timelib_add', this does not support more complex statements such as "next
1083  * workday".
1084  */
1085 timelib_time *timelib_sub(timelib_time *t, timelib_rel_time *interval);
1086 timelib_time *timelib_sub_wall(timelib_time *t, timelib_rel_time *interval);
1087 
1088 /* from parse_posix.c */
1089 
1090 void timelib_posix_str_dtor(timelib_posix_str *ps);
1091 
1092 timelib_posix_str* timelib_parse_posix_str(const char *posix);
1093 
1094 /**
1095  * Calculate the two yearly to/from DST
1096  */
1097 void timelib_get_transitions_for_year(timelib_tzinfo *tz, timelib_sll year, timelib_posix_transitions *transitions);
1098 
1099 
1100 #ifdef __cplusplus
1101 } /* extern "C" */
1102 #endif
1103 
1104 #endif
1105