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