xref: /PHP-7.4/ext/date/lib/timelib.h (revision 778902db)
14fb4cac6SDerick Rethans /*
2fab5cbabSDerick Rethans  * The MIT License (MIT)
3fab5cbabSDerick Rethans  *
4aae5907cSDerick Rethans  * Copyright (c) 2015-2019 Derick Rethans
5aae5907cSDerick Rethans  * Copyright (c) 2018 MongoDB, Inc.
6fab5cbabSDerick Rethans  *
7fab5cbabSDerick Rethans  * Permission is hereby granted, free of charge, to any person obtaining a copy
8fab5cbabSDerick Rethans  * of this software and associated documentation files (the "Software"), to deal
9fab5cbabSDerick Rethans  * in the Software without restriction, including without limitation the rights
10fab5cbabSDerick Rethans  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11fab5cbabSDerick Rethans  * copies of the Software, and to permit persons to whom the Software is
12fab5cbabSDerick Rethans  * furnished to do so, subject to the following conditions:
13fab5cbabSDerick Rethans  *
14fab5cbabSDerick Rethans  * The above copyright notice and this permission notice shall be included in
15fab5cbabSDerick Rethans  * all copies or substantial portions of the Software.
16fab5cbabSDerick Rethans  *
17fab5cbabSDerick Rethans  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18fab5cbabSDerick Rethans  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19fab5cbabSDerick Rethans  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20fab5cbabSDerick Rethans  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21fab5cbabSDerick Rethans  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22fab5cbabSDerick Rethans  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23fab5cbabSDerick Rethans  * THE SOFTWARE.
244fb4cac6SDerick Rethans  */
254fb4cac6SDerick Rethans 
26a736f99eSfoobar #ifndef __TIMELIB_H__
27a736f99eSfoobar #define __TIMELIB_H__
28a736f99eSfoobar 
29584db6f3SDerick Rethans #ifdef HAVE_TIMELIB_CONFIG_H
30584db6f3SDerick Rethans # include "timelib_config.h"
31584db6f3SDerick Rethans #endif
32584db6f3SDerick Rethans 
33584db6f3SDerick Rethans #include <stdlib.h>
3409340ea9SDerick Rethans #include <stdbool.h>
357c46f35dSDerick Rethans #include <limits.h>
36584db6f3SDerick Rethans #include <inttypes.h>
37584db6f3SDerick Rethans 
38584db6f3SDerick Rethans # ifndef HAVE_INT32_T
39584db6f3SDerick Rethans #  if SIZEOF_INT == 4
40584db6f3SDerick Rethans typedef int int32_t;
41584db6f3SDerick Rethans #  elif SIZEOF_LONG == 4
42584db6f3SDerick Rethans typedef long int int32_t;
43584db6f3SDerick Rethans #  endif
44584db6f3SDerick Rethans # endif
45584db6f3SDerick Rethans 
46584db6f3SDerick Rethans # ifndef HAVE_UINT32_T
47584db6f3SDerick Rethans #  if SIZEOF_INT == 4
48584db6f3SDerick Rethans typedef unsigned int uint32_t;
49584db6f3SDerick Rethans #  elif SIZEOF_LONG == 4
50584db6f3SDerick Rethans typedef unsigned long int uint32_t;
51584db6f3SDerick Rethans #  endif
52584db6f3SDerick Rethans # endif
53584db6f3SDerick Rethans 
54584db6f3SDerick Rethans #ifdef _WIN32
55584db6f3SDerick Rethans # if _MSC_VER >= 1600
56584db6f3SDerick Rethans # include <stdint.h>
57584db6f3SDerick Rethans # endif
58584db6f3SDerick Rethans # ifndef SIZEOF_INT
59584db6f3SDerick Rethans #  define SIZEOF_INT 4
60584db6f3SDerick Rethans # endif
61584db6f3SDerick Rethans # ifndef SIZEOF_LONG
62584db6f3SDerick Rethans #  define SIZEOF_LONG 4
63584db6f3SDerick Rethans # endif
64584db6f3SDerick Rethans # ifndef int32_t
65584db6f3SDerick Rethans typedef __int32           int32_t;
66584db6f3SDerick Rethans # endif
67584db6f3SDerick Rethans # ifndef uint32_t
68584db6f3SDerick Rethans typedef unsigned __int32  uint32_t;
69584db6f3SDerick Rethans # endif
70584db6f3SDerick Rethans # ifndef int64_t
71584db6f3SDerick Rethans typedef __int64           int64_t;
72584db6f3SDerick Rethans # endif
73584db6f3SDerick Rethans # ifndef uint64_t
74584db6f3SDerick Rethans typedef unsigned __int64  uint64_t;
75584db6f3SDerick Rethans # endif
76584db6f3SDerick Rethans # ifndef PRId32
77584db6f3SDerick Rethans #  define PRId32       "I32d"
78584db6f3SDerick Rethans # endif
79584db6f3SDerick Rethans # ifndef PRIu32
80584db6f3SDerick Rethans #  define PRIu32       "I32u"
81584db6f3SDerick Rethans # endif
82584db6f3SDerick Rethans # ifndef PRId64
83584db6f3SDerick Rethans #  define PRId64       "I64d"
84584db6f3SDerick Rethans # endif
85584db6f3SDerick Rethans # ifndef PRIu64
86584db6f3SDerick Rethans #  define PRIu64       "I64u"
87584db6f3SDerick Rethans # endif
88584db6f3SDerick Rethans # ifndef INT32_MAX
89584db6f3SDerick Rethans #define INT32_MAX    _I32_MAX
90584db6f3SDerick Rethans # endif
91584db6f3SDerick Rethans # ifndef INT32_MIN
92584db6f3SDerick Rethans #define INT32_MIN    ((int32_t)_I32_MIN)
93584db6f3SDerick Rethans # endif
94584db6f3SDerick Rethans # ifndef UINT32_MAX
95584db6f3SDerick Rethans #define UINT32_MAX   _UI32_MAX
96584db6f3SDerick Rethans # endif
97584db6f3SDerick Rethans # ifndef INT64_MIN
98584db6f3SDerick Rethans #define INT64_MIN    ((int64_t)_I64_MIN)
99584db6f3SDerick Rethans # endif
100584db6f3SDerick Rethans # ifndef INT64_MAX
101584db6f3SDerick Rethans #define INT64_MAX    _I64_MAX
102584db6f3SDerick Rethans # endif
103584db6f3SDerick Rethans # ifndef UINT64_MAX
104584db6f3SDerick Rethans #define UINT64_MAX   _UI64_MAX
105584db6f3SDerick Rethans # endif
106584db6f3SDerick Rethans #endif
107584db6f3SDerick Rethans 
108584db6f3SDerick Rethans #if (defined(__x86_64__) || defined(__LP64__) || defined(_LP64) || defined(_WIN64)) && !defined(TIMELIB_FORCE_LONG32)
109584db6f3SDerick Rethans typedef int64_t timelib_long;
110584db6f3SDerick Rethans typedef uint64_t timelib_ulong;
111584db6f3SDerick Rethans # define TIMELIB_LONG_MAX INT64_MAX
112584db6f3SDerick Rethans # define TIMELIB_LONG_MIN INT64_MIN
113584db6f3SDerick Rethans # define TIMELIB_ULONG_MAX UINT64_MAX
114584db6f3SDerick Rethans # define TIMELIB_LONG_FMT "%" PRId64
115584db6f3SDerick Rethans # define TIMELIB_ULONG_FMT "%" PRIu64
116584db6f3SDerick Rethans #else
117584db6f3SDerick Rethans typedef int32_t timelib_long;
118584db6f3SDerick Rethans typedef uint32_t timelib_ulong;
119584db6f3SDerick Rethans # define TIMELIB_LONG_MAX INT32_MAX
120584db6f3SDerick Rethans # define TIMELIB_LONG_MIN INT32_MIN
121584db6f3SDerick Rethans # define TIMELIB_ULONG_MAX UINT32_MAX
122584db6f3SDerick Rethans # define TIMELIB_LONG_FMT "%" PRId32
123584db6f3SDerick Rethans # define TIMELIB_ULONG_FMT "%" PRIu32
1247c46f35dSDerick Rethans #endif
1254fb4cac6SDerick Rethans 
126584db6f3SDerick Rethans #if defined(_MSC_VER)
127584db6f3SDerick Rethans typedef uint64_t timelib_ull;
128584db6f3SDerick Rethans typedef int64_t timelib_sll;
129584db6f3SDerick Rethans # define TIMELIB_LL_CONST(n) n ## i64
130584db6f3SDerick Rethans #else
131584db6f3SDerick Rethans typedef unsigned long long timelib_ull;
132584db6f3SDerick Rethans typedef signed long long timelib_sll;
133584db6f3SDerick Rethans # define TIMELIB_LL_CONST(n) n ## ll
134584db6f3SDerick Rethans #endif
135584db6f3SDerick Rethans 
136c0383b50SDerick Rethans typedef struct _ttinfo ttinfo;
137c0383b50SDerick Rethans typedef struct _tlinfo tlinfo;
138584db6f3SDerick Rethans 
139c0383b50SDerick Rethans typedef struct _tlocinfo
140584db6f3SDerick Rethans {
141584db6f3SDerick Rethans 	char country_code[3];
142584db6f3SDerick Rethans 	double latitude;
143584db6f3SDerick Rethans 	double longitude;
144584db6f3SDerick Rethans 	char *comments;
145584db6f3SDerick Rethans } tlocinfo;
146584db6f3SDerick Rethans 
147c0383b50SDerick Rethans typedef struct _timelib_tzinfo
148584db6f3SDerick Rethans {
149584db6f3SDerick Rethans 	char    *name;
150584db6f3SDerick Rethans 	struct {
151584db6f3SDerick Rethans 		uint32_t ttisgmtcnt;
152584db6f3SDerick Rethans 		uint32_t ttisstdcnt;
153584db6f3SDerick Rethans 		uint32_t leapcnt;
154584db6f3SDerick Rethans 		uint32_t timecnt;
155584db6f3SDerick Rethans 		uint32_t typecnt;
156584db6f3SDerick Rethans 		uint32_t charcnt;
1573e4a3d00SDerick Rethans 	} _bit32;
158584db6f3SDerick Rethans 	struct {
159584db6f3SDerick Rethans 		uint64_t ttisgmtcnt;
160584db6f3SDerick Rethans 		uint64_t ttisstdcnt;
161584db6f3SDerick Rethans 		uint64_t leapcnt;
162584db6f3SDerick Rethans 		uint64_t timecnt;
163584db6f3SDerick Rethans 		uint64_t typecnt;
164584db6f3SDerick Rethans 		uint64_t charcnt;
165584db6f3SDerick Rethans 	} bit64;
166584db6f3SDerick Rethans 
1673e4a3d00SDerick Rethans 	int64_t *trans;
168584db6f3SDerick Rethans 	unsigned char *trans_idx;
169584db6f3SDerick Rethans 
170584db6f3SDerick Rethans 	ttinfo  *type;
171584db6f3SDerick Rethans 	char    *timezone_abbr;
172584db6f3SDerick Rethans 
173584db6f3SDerick Rethans 	tlinfo  *leap_times;
174584db6f3SDerick Rethans 	unsigned char bc;
175584db6f3SDerick Rethans 	tlocinfo location;
176584db6f3SDerick Rethans } timelib_tzinfo;
177584db6f3SDerick Rethans 
178c0383b50SDerick Rethans typedef struct _timelib_rel_time {
179584db6f3SDerick Rethans 	timelib_sll y, m, d; /* Years, Months and Days */
180584db6f3SDerick Rethans 	timelib_sll h, i, s; /* Hours, mInutes and Seconds */
181584db6f3SDerick Rethans 	timelib_sll us;      /* Microseconds */
182584db6f3SDerick Rethans 
183584db6f3SDerick Rethans 	int weekday; /* Stores the day in 'next monday' */
184584db6f3SDerick Rethans 	int weekday_behavior; /* 0: the current day should *not* be counted when advancing forwards; 1: the current day *should* be counted */
185584db6f3SDerick Rethans 
186584db6f3SDerick Rethans 	int first_last_day_of;
187584db6f3SDerick Rethans 	int invert; /* Whether the difference should be inverted */
188584db6f3SDerick Rethans 	timelib_sll days; /* Contains the number of *days*, instead of Y-M-D differences */
189584db6f3SDerick Rethans 
190584db6f3SDerick Rethans 	struct {
191584db6f3SDerick Rethans 		unsigned int type;
192584db6f3SDerick Rethans 		timelib_sll amount;
193584db6f3SDerick Rethans 	} special;
194584db6f3SDerick Rethans 
195584db6f3SDerick Rethans 	unsigned int   have_weekday_relative, have_special_relative;
196584db6f3SDerick Rethans } timelib_rel_time;
197584db6f3SDerick Rethans 
198c0383b50SDerick Rethans typedef struct _timelib_time_offset {
199584db6f3SDerick Rethans 	int32_t      offset;
200584db6f3SDerick Rethans 	unsigned int leap_secs;
201584db6f3SDerick Rethans 	unsigned int is_dst;
202584db6f3SDerick Rethans 	char        *abbr;
203584db6f3SDerick Rethans 	timelib_sll  transition_time;
204584db6f3SDerick Rethans } timelib_time_offset;
205584db6f3SDerick Rethans 
206c0383b50SDerick Rethans typedef struct _timelib_time {
207584db6f3SDerick Rethans 	timelib_sll      y, m, d;     /* Year, Month, Day */
208584db6f3SDerick Rethans 	timelib_sll      h, i, s;     /* Hour, mInute, Second */
209584db6f3SDerick Rethans 	timelib_sll      us;          /* Microseconds */
210584db6f3SDerick Rethans 	int              z;           /* UTC offset in seconds */
211584db6f3SDerick Rethans 	char            *tz_abbr;     /* Timezone abbreviation (display only) */
212584db6f3SDerick Rethans 	timelib_tzinfo  *tz_info;     /* Timezone structure */
213584db6f3SDerick Rethans 	signed int       dst;         /* Flag if we were parsing a DST zone */
214584db6f3SDerick Rethans 	timelib_rel_time relative;
215584db6f3SDerick Rethans 
216584db6f3SDerick Rethans 	timelib_sll      sse;         /* Seconds since epoch */
217584db6f3SDerick Rethans 
218584db6f3SDerick Rethans 	unsigned int   have_time, have_date, have_zone, have_relative, have_weeknr_day;
219584db6f3SDerick Rethans 
220584db6f3SDerick Rethans 	unsigned int   sse_uptodate; /* !0 if the sse member is up to date with the date/time members */
221584db6f3SDerick Rethans 	unsigned int   tim_uptodate; /* !0 if the date/time members are up to date with the sse member */
222584db6f3SDerick Rethans 	unsigned int   is_localtime; /*  1 if the current struct represents localtime, 0 if it is in GMT */
223584db6f3SDerick Rethans 	unsigned int   zone_type;    /*  1 time offset,
224584db6f3SDerick Rethans 	                              *  3 TimeZone identifier,
225584db6f3SDerick Rethans 	                              *  2 TimeZone abbreviation */
226584db6f3SDerick Rethans } timelib_time;
227584db6f3SDerick Rethans 
228c0383b50SDerick Rethans typedef struct _timelib_abbr_info {
229584db6f3SDerick Rethans 	timelib_sll  utc_offset;
230584db6f3SDerick Rethans 	char        *abbr;
231584db6f3SDerick Rethans 	int          dst;
232584db6f3SDerick Rethans } timelib_abbr_info;
233584db6f3SDerick Rethans 
234584db6f3SDerick Rethans #define TIMELIB_WARN_MASK                      0x1ff
235584db6f3SDerick Rethans #define TIMELIB_ERR_MASK                       0x2ff
236584db6f3SDerick Rethans 
237584db6f3SDerick Rethans #define TIMELIB_WARN_DOUBLE_TZ                 0x101
238584db6f3SDerick Rethans #define TIMELIB_WARN_INVALID_TIME              0x102
239584db6f3SDerick Rethans #define TIMELIB_WARN_INVALID_DATE              0x103
240584db6f3SDerick Rethans #define TIMELIB_WARN_TRAILING_DATA             0x11a
241584db6f3SDerick Rethans 
242584db6f3SDerick Rethans #define TIMELIB_ERR_DOUBLE_TZ                  0x201
243584db6f3SDerick Rethans #define TIMELIB_ERR_TZID_NOT_FOUND             0x202
244584db6f3SDerick Rethans #define TIMELIB_ERR_DOUBLE_TIME                0x203
245584db6f3SDerick Rethans #define TIMELIB_ERR_DOUBLE_DATE                0x204
246584db6f3SDerick Rethans #define TIMELIB_ERR_UNEXPECTED_CHARACTER       0x205
247584db6f3SDerick Rethans #define TIMELIB_ERR_EMPTY_STRING               0x206
248584db6f3SDerick Rethans #define TIMELIB_ERR_UNEXPECTED_DATA            0x207
249584db6f3SDerick Rethans #define TIMELIB_ERR_NO_TEXTUAL_DAY             0x208
250584db6f3SDerick Rethans #define TIMELIB_ERR_NO_TWO_DIGIT_DAY           0x209
251584db6f3SDerick Rethans #define TIMELIB_ERR_NO_THREE_DIGIT_DAY_OF_YEAR 0x20a
252584db6f3SDerick Rethans #define TIMELIB_ERR_NO_TWO_DIGIT_MONTH         0x20b
253584db6f3SDerick Rethans #define TIMELIB_ERR_NO_TEXTUAL_MONTH           0x20c
254584db6f3SDerick Rethans #define TIMELIB_ERR_NO_TWO_DIGIT_YEAR          0x20d
255584db6f3SDerick Rethans #define TIMELIB_ERR_NO_FOUR_DIGIT_YEAR         0x20e
256584db6f3SDerick Rethans #define TIMELIB_ERR_NO_TWO_DIGIT_HOUR          0x20f
257584db6f3SDerick Rethans #define TIMELIB_ERR_HOUR_LARGER_THAN_12        0x210
258584db6f3SDerick Rethans #define TIMELIB_ERR_MERIDIAN_BEFORE_HOUR       0x211
259584db6f3SDerick Rethans #define TIMELIB_ERR_NO_MERIDIAN                0x212
260584db6f3SDerick Rethans #define TIMELIB_ERR_NO_TWO_DIGIT_MINUTE        0x213
261584db6f3SDerick Rethans #define TIMELIB_ERR_NO_TWO_DIGIT_SECOND        0x214
262584db6f3SDerick Rethans #define TIMELIB_ERR_NO_SIX_DIGIT_MICROSECOND   0x215
263584db6f3SDerick Rethans #define TIMELIB_ERR_NO_SEP_SYMBOL              0x216
264584db6f3SDerick Rethans #define TIMELIB_ERR_EXPECTED_ESCAPE_CHAR       0x217
265584db6f3SDerick Rethans #define TIMELIB_ERR_NO_ESCAPED_CHAR            0x218
266584db6f3SDerick Rethans #define TIMELIB_ERR_WRONG_FORMAT_SEP           0x219
267584db6f3SDerick Rethans #define TIMELIB_ERR_TRAILING_DATA              0x21a
268584db6f3SDerick Rethans #define TIMELIB_ERR_DATA_MISSING               0x21b
26909340ea9SDerick Rethans #define TIMELIB_ERR_NO_THREE_DIGIT_MILLISECOND 0x21c
27009340ea9SDerick Rethans #define TIMELIB_ERR_NO_FOUR_DIGIT_YEAR_ISO     0x21d
27109340ea9SDerick Rethans #define TIMELIB_ERR_NO_TWO_DIGIT_WEEK          0x21e
27209340ea9SDerick Rethans #define TIMELIB_ERR_INVALID_WEEK               0x21f
27309340ea9SDerick Rethans #define TIMELIB_ERR_NO_DAY_OF_WEEK             0x220
27409340ea9SDerick Rethans #define TIMELIB_ERR_INVALID_DAY_OF_WEEK        0x221
27509340ea9SDerick Rethans #define TIMELIB_ERR_INVALID_SPECIFIER          0x222
27609340ea9SDerick Rethans #define TIMELIB_ERR_INVALID_TZ_OFFSET          0x223
27709340ea9SDerick Rethans #define TIMELIB_ERR_FORMAT_LITERAL_MISMATCH    0x224
27809340ea9SDerick Rethans #define TIMELIB_ERR_MIX_ISO_WITH_NATURAL       0x225
279584db6f3SDerick Rethans 
280584db6f3SDerick Rethans #define TIMELIB_ZONETYPE_OFFSET 1
281584db6f3SDerick Rethans #define TIMELIB_ZONETYPE_ABBR   2
282584db6f3SDerick Rethans #define TIMELIB_ZONETYPE_ID     3
283584db6f3SDerick Rethans 
284c0383b50SDerick Rethans typedef struct _timelib_error_message {
285584db6f3SDerick Rethans 	int         error_code;
286584db6f3SDerick Rethans 	int         position;
287584db6f3SDerick Rethans 	char        character;
288584db6f3SDerick Rethans 	char       *message;
289584db6f3SDerick Rethans } timelib_error_message;
290584db6f3SDerick Rethans 
291c0383b50SDerick Rethans typedef struct _timelib_error_container {
292c0383b50SDerick Rethans 	timelib_error_message *error_messages;
293c0383b50SDerick Rethans 	timelib_error_message *warning_messages;
294c0383b50SDerick Rethans 	int                    error_count;
295c0383b50SDerick Rethans 	int                    warning_count;
296584db6f3SDerick Rethans } timelib_error_container;
297584db6f3SDerick Rethans 
298584db6f3SDerick Rethans typedef struct _timelib_tz_lookup_table {
299584db6f3SDerick Rethans 	char       *name;
300584db6f3SDerick Rethans 	int         type;
301584db6f3SDerick Rethans 	float       gmtoffset;
302584db6f3SDerick Rethans 	char       *full_tz_name;
303584db6f3SDerick Rethans } timelib_tz_lookup_table;
304584db6f3SDerick Rethans 
305584db6f3SDerick Rethans typedef struct _timelib_tzdb_index_entry {
306584db6f3SDerick Rethans 	char *id;
307584db6f3SDerick Rethans 	unsigned int pos;
308584db6f3SDerick Rethans } timelib_tzdb_index_entry;
309584db6f3SDerick Rethans 
310584db6f3SDerick Rethans typedef struct _timelib_tzdb {
311584db6f3SDerick Rethans 	char                           *version;
312584db6f3SDerick Rethans 	int                             index_size;
313584db6f3SDerick Rethans 	const timelib_tzdb_index_entry *index;
314584db6f3SDerick Rethans 	const unsigned char            *data;
315584db6f3SDerick Rethans } timelib_tzdb;
316584db6f3SDerick Rethans 
31796d1d13dSDerick Rethans #ifndef timelib_malloc
31896d1d13dSDerick Rethans # define timelib_malloc  malloc
31996d1d13dSDerick Rethans # define timelib_realloc realloc
32096d1d13dSDerick Rethans # define timelib_calloc  calloc
32196d1d13dSDerick Rethans # define timelib_strdup  strdup
32296d1d13dSDerick Rethans # define timelib_free    free
32396d1d13dSDerick Rethans #endif
32496d1d13dSDerick Rethans 
325*778902dbSDerick Rethans #define TIMELIB_VERSION 201804
326*778902dbSDerick Rethans #define TIMELIB_EXTENDED_VERSION 20180401
327*778902dbSDerick Rethans #define TIMELIB_ASCII_VERSION "2018.04"
328dd68a623SScott MacVicar 
3294fb4cac6SDerick Rethans #define TIMELIB_NONE             0x00
3304fb4cac6SDerick Rethans #define TIMELIB_OVERRIDE_TIME    0x01
331aea378c9SDerick Rethans #define TIMELIB_NO_CLONE         0x02
3324fb4cac6SDerick Rethans 
3335b2ce47fSDerick Rethans #define TIMELIB_UNSET   -99999
3345b2ce47fSDerick Rethans 
335584db6f3SDerick Rethans /* An entry for each of these error codes is also in the
336584db6f3SDerick Rethans  * timelib_error_messages array in timelib.c */
337584db6f3SDerick Rethans #define TIMELIB_ERROR_NO_ERROR                            0x00
338584db6f3SDerick Rethans #define TIMELIB_ERROR_CANNOT_ALLOCATE                     0x01
339584db6f3SDerick Rethans #define TIMELIB_ERROR_CORRUPT_TRANSITIONS_DONT_INCREASE   0x02
340584db6f3SDerick Rethans #define TIMELIB_ERROR_CORRUPT_NO_64BIT_PREAMBLE           0x03
341584db6f3SDerick Rethans #define TIMELIB_ERROR_CORRUPT_NO_ABBREVIATION             0x04
342584db6f3SDerick Rethans #define TIMELIB_ERROR_UNSUPPORTED_VERSION                 0x05
343584db6f3SDerick Rethans #define TIMELIB_ERROR_NO_SUCH_TIMEZONE                    0x06
34428999771SEdin Kadribasic 
345584db6f3SDerick Rethans #ifdef __cplusplus
346584db6f3SDerick Rethans extern "C" {
347f94b3012Sfoobar #endif
348f94b3012Sfoobar 
34909340ea9SDerick Rethans typedef enum _timelib_format_specifier_code {
35009340ea9SDerick Rethans 	TIMELIB_FORMAT_ALLOW_EXTRA_CHARACTERS = 0,
35109340ea9SDerick Rethans 	TIMELIB_FORMAT_ANY_SEPARATOR,
35209340ea9SDerick Rethans 	TIMELIB_FORMAT_DAY_TWO_DIGIT,
35309340ea9SDerick Rethans 	TIMELIB_FORMAT_DAY_TWO_DIGIT_PADDED,
35409340ea9SDerick Rethans 	TIMELIB_FORMAT_DAY_OF_WEEK_ISO,
35509340ea9SDerick Rethans 	TIMELIB_FORMAT_DAY_OF_WEEK,
35609340ea9SDerick Rethans 	TIMELIB_FORMAT_DAY_OF_YEAR,
35709340ea9SDerick Rethans 	TIMELIB_FORMAT_DAY_SUFFIX,
35809340ea9SDerick Rethans 	TIMELIB_FORMAT_END,
35909340ea9SDerick Rethans 	TIMELIB_FORMAT_EPOCH_SECONDS,
36009340ea9SDerick Rethans 	TIMELIB_FORMAT_ESCAPE,
36109340ea9SDerick Rethans 	TIMELIB_FORMAT_HOUR_TWO_DIGIT_12_MAX,
36209340ea9SDerick Rethans 	TIMELIB_FORMAT_HOUR_TWO_DIGIT_12_MAX_PADDED,
36309340ea9SDerick Rethans 	TIMELIB_FORMAT_HOUR_TWO_DIGIT_24_MAX,
36409340ea9SDerick Rethans 	TIMELIB_FORMAT_HOUR_TWO_DIGIT_24_MAX_PADDED,
36509340ea9SDerick Rethans 	TIMELIB_FORMAT_LITERAL,
36609340ea9SDerick Rethans 	TIMELIB_FORMAT_MERIDIAN,
36709340ea9SDerick Rethans 	TIMELIB_FORMAT_MICROSECOND_SIX_DIGIT,
36809340ea9SDerick Rethans 	TIMELIB_FORMAT_MILLISECOND_THREE_DIGIT,
36909340ea9SDerick Rethans 	TIMELIB_FORMAT_MINUTE_TWO_DIGIT,
37009340ea9SDerick Rethans 	TIMELIB_FORMAT_MONTH_TWO_DIGIT,
37109340ea9SDerick Rethans 	TIMELIB_FORMAT_MONTH_TWO_DIGIT_PADDED,
37209340ea9SDerick Rethans 	TIMELIB_FORMAT_RANDOM_CHAR,
37309340ea9SDerick Rethans 	TIMELIB_FORMAT_RESET_ALL,
37409340ea9SDerick Rethans 	TIMELIB_FORMAT_RESET_ALL_WHEN_NOT_SET,
37509340ea9SDerick Rethans 	TIMELIB_FORMAT_SECOND_TWO_DIGIT,
37609340ea9SDerick Rethans 	TIMELIB_FORMAT_SEPARATOR,
37709340ea9SDerick Rethans 	TIMELIB_FORMAT_SKIP_TO_SEPARATOR,
37809340ea9SDerick Rethans 	TIMELIB_FORMAT_TEXTUAL_DAY_3_LETTER,
37909340ea9SDerick Rethans 	TIMELIB_FORMAT_TEXTUAL_DAY_FULL,
38009340ea9SDerick Rethans 	TIMELIB_FORMAT_TEXTUAL_MONTH_3_LETTER,
38109340ea9SDerick Rethans 	TIMELIB_FORMAT_TEXTUAL_MONTH_FULL,
38209340ea9SDerick Rethans 	TIMELIB_FORMAT_TIMEZONE_OFFSET,
38309340ea9SDerick Rethans 	TIMELIB_FORMAT_TIMEZONE_OFFSET_MINUTES,
38409340ea9SDerick Rethans 	TIMELIB_FORMAT_WEEK_OF_YEAR_ISO,
38509340ea9SDerick Rethans 	TIMELIB_FORMAT_WEEK_OF_YEAR,
38609340ea9SDerick Rethans 	TIMELIB_FORMAT_WHITESPACE,
38709340ea9SDerick Rethans 	TIMELIB_FORMAT_YEAR_TWO_DIGIT,
38809340ea9SDerick Rethans 	TIMELIB_FORMAT_YEAR_FOUR_DIGIT,
38909340ea9SDerick Rethans 	TIMELIB_FORMAT_YEAR_ISO
39009340ea9SDerick Rethans } timelib_format_specifier_code;
39109340ea9SDerick Rethans 
39209340ea9SDerick Rethans typedef struct _timelib_format_specifier {
39309340ea9SDerick Rethans 	char                          specifier;
39409340ea9SDerick Rethans 	timelib_format_specifier_code code;
39509340ea9SDerick Rethans } timelib_format_specifier;
39609340ea9SDerick Rethans 
39709340ea9SDerick Rethans typedef struct _timelib_format_config {
39809340ea9SDerick Rethans 	const timelib_format_specifier *format_map;
39909340ea9SDerick Rethans 	/* Format speciifiers must be preceded by 'prefix_char' if not '\0'. */
40009340ea9SDerick Rethans 	char                            prefix_char;
40109340ea9SDerick Rethans } timelib_format_config;
40209340ea9SDerick Rethans 
4035b2ce47fSDerick Rethans /* Function pointers */
404584db6f3SDerick Rethans typedef timelib_tzinfo* (*timelib_tz_get_wrapper)(char *tzname, const timelib_tzdb *tzdb, int *error_code);
4055b2ce47fSDerick Rethans 
4064fb4cac6SDerick Rethans /* From dow.c */
407584db6f3SDerick Rethans /* Calculates the day of the week from y, m, and d. 0=Sunday..6=Saturday */
408eb8b4fd4SDerick Rethans timelib_sll timelib_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d);
409584db6f3SDerick Rethans 
410584db6f3SDerick Rethans /* Calculates the day of the ISO week from y, m, and d. 1=Monday, 7=Sunday */
41132173222SDerick Rethans timelib_sll timelib_iso_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d);
412584db6f3SDerick Rethans 
413584db6f3SDerick Rethans /* Calculates the day of the year according to y-m-d. 0=Jan 1st..364/365=Dec
414584db6f3SDerick Rethans  * 31st */
415e155585eSDerick Rethans timelib_sll timelib_day_of_year(timelib_sll y, timelib_sll m, timelib_sll d);
416584db6f3SDerick Rethans 
417584db6f3SDerick Rethans /* Calculates the day of the year according to y-w-dow. 0..364/365 */
418584db6f3SDerick Rethans timelib_sll timelib_daynr_from_weeknr(timelib_sll iy, timelib_sll iw, timelib_sll id);
419584db6f3SDerick Rethans 
420584db6f3SDerick Rethans /* Calculates the number of days in month m for year y. 28..31 */
421e155585eSDerick Rethans timelib_sll timelib_days_in_month(timelib_sll y, timelib_sll m);
422584db6f3SDerick Rethans 
423584db6f3SDerick Rethans /* Calculates the ISO year and week from y, m, and d, into iw and iy */
424e155585eSDerick Rethans void timelib_isoweek_from_date(timelib_sll y, timelib_sll m, timelib_sll d, timelib_sll *iw, timelib_sll *iy);
425584db6f3SDerick Rethans 
426584db6f3SDerick Rethans /* Calculates the ISO year, week, and day of week from y, m, and d, into iy,
427584db6f3SDerick Rethans  * iw, and id */
428584db6f3SDerick Rethans void timelib_isodate_from_date(timelib_sll y, timelib_sll m, timelib_sll d, timelib_sll *iy, timelib_sll *iw, timelib_sll *id);
429584db6f3SDerick Rethans 
430584db6f3SDerick Rethans /* Calculates the year, month, and day from iy, iw, and iw, into y, m, and d */
431584db6f3SDerick Rethans void timelib_date_from_isodate(timelib_sll iy, timelib_sll iw, timelib_sll id, timelib_sll *y, timelib_sll *m, timelib_sll *d);
432584db6f3SDerick Rethans 
433584db6f3SDerick Rethans /* Returns true if h, i and s fit in the range 00:00:00..23:59:59, false
434584db6f3SDerick Rethans  * otherwise */
4353df7836dSDerick Rethans int timelib_valid_time(timelib_sll h, timelib_sll i, timelib_sll s);
436584db6f3SDerick Rethans 
437584db6f3SDerick Rethans /* Returns true if m fits in the range 1..12, and d fits in the range
438584db6f3SDerick Rethans  * 1..<days-in-month> for year y */
439c76ba173SDerick Rethans int timelib_valid_date(timelib_sll y, timelib_sll m, timelib_sll d);
4404fb4cac6SDerick Rethans 
4414fb4cac6SDerick Rethans /* From parse_date.re */
442584db6f3SDerick Rethans 
443584db6f3SDerick Rethans /* Parses the date/time string in 's' with length 'len' into the constituent
444584db6f3SDerick Rethans  * parts of timelib_time*.
445584db6f3SDerick Rethans  *
446584db6f3SDerick Rethans  * Depending on the contents of the string 's', not all elements might be
447584db6f3SDerick Rethans  * filled. You can check whether a specific element has been parsed by
448584db6f3SDerick Rethans  * comparing with the TIMELIB_UNSET define.
449584db6f3SDerick Rethans  *
450584db6f3SDerick Rethans  * If errors occur, this function keeps already parsed elements in the
451584db6f3SDerick Rethans  * returned timelib_time* value.
452584db6f3SDerick Rethans  *
453584db6f3SDerick Rethans  * If the **errors points to a timelib_error_container variable, warnings
454584db6f3SDerick Rethans  * and errors will be recorded. You are responsible for freeing the stored
455584db6f3SDerick Rethans  * information with timelib_error_container_dtor(). To see whether errors have
4569c608bd1SDerick Rethans  * occurred, inspect errors->errors_count. To see whether warnings have occurred,
457584db6f3SDerick Rethans  * inspect errors->warnings_count.
458584db6f3SDerick Rethans  *
459584db6f3SDerick Rethans  * The returned timelib_time* value is dynamically allocated and should be
460584db6f3SDerick Rethans  * freed with timelib_time_dtor().
461584db6f3SDerick Rethans  */
462fab5cbabSDerick Rethans timelib_time *timelib_strtotime(char *s, size_t len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper);
463584db6f3SDerick Rethans 
464584db6f3SDerick Rethans /* Parses the date/time string in 's' with length 'len' into the constituent
465584db6f3SDerick Rethans  * parts of timelib_time* according to the format in 'format'.
466584db6f3SDerick Rethans  *
467584db6f3SDerick Rethans  * Depending on the contents of the string 's', not all elements might be
468584db6f3SDerick Rethans  * filled. You can check whether a specific element has been parsed by
469584db6f3SDerick Rethans  * comparing with the TIMELIB_UNSET define.
470584db6f3SDerick Rethans  *
471584db6f3SDerick Rethans  * If errors occur, this function keeps already parsed elements in the
472584db6f3SDerick Rethans  * returned timelib_time* value.
473584db6f3SDerick Rethans  *
474584db6f3SDerick Rethans  * If the **errors points to a timelib_error_container variable, warnings
475584db6f3SDerick Rethans  * and errors will be recorded. You are responsible for freeing the stored
476584db6f3SDerick Rethans  * information with timelib_error_container_dtor(). To see whether errors have
4779c608bd1SDerick Rethans  * occurred, inspect errors->errors_count. To see whether warnings have occurred,
478584db6f3SDerick Rethans  * inspect errors->warnings_count.
479584db6f3SDerick Rethans  *
480584db6f3SDerick Rethans  * The returned timelib_time* value is dynamically allocated and should be
481584db6f3SDerick Rethans  * freed with timelib_time_dtor().
482584db6f3SDerick Rethans  */
483fab5cbabSDerick Rethans 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);
484584db6f3SDerick Rethans 
48509340ea9SDerick Rethans /* Parses the date/time string in 's' with length 'len' into the constituent
48609340ea9SDerick Rethans  * parts of timelib_time* according to the format in 'format' with format
48709340ea9SDerick Rethans  * specifier configuration 'format_config'.
48809340ea9SDerick Rethans  *
48909340ea9SDerick Rethans  * 'format_map' is an array of pairs, with the first element being the format
49009340ea9SDerick Rethans  * specifier as a character and the second element corresponds to the
49109340ea9SDerick Rethans  * representation of the specifier from the enum list
49209340ea9SDerick Rethans  * 'timelib_format_specifier_code'.
49309340ea9SDerick Rethans  *
49409340ea9SDerick Rethans  * Note: 'format_map' must be terminated with specifier '\0' to indicate to the
49509340ea9SDerick Rethans  * parser that there are no more format specifiers in the list.
49609340ea9SDerick Rethans  */
49709340ea9SDerick Rethans timelib_time *timelib_parse_from_format_with_map(char *format, 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);
49809340ea9SDerick Rethans 
499584db6f3SDerick Rethans /* Fills the gaps in the parsed timelib_time with information from the reference date/time in 'now'
500584db6f3SDerick Rethans  *
501584db6f3SDerick Rethans  * If any of the 'parsed' y, m, d, h, i or s parameters is unset (TIMELIB_UNSET):
502584db6f3SDerick Rethans  * - if microtime (us) is unset, then the us of the parsed time is set to 0.
503584db6f3SDerick Rethans  * - else if microtime (us) is unset and 'now'->'us' is set, use it, otherwise use 0.
504584db6f3SDerick Rethans  *
505584db6f3SDerick Rethans  * For either of the 'parsed' y, m, d, h, i, s, z (utc offset in seconds) or
506584db6f3SDerick Rethans  * dst is unset, set it to the corresponding value in 'now' if set, otherwise
507584db6f3SDerick Rethans  * set it to 0.
508584db6f3SDerick Rethans  *
509584db6f3SDerick Rethans  * It duplicates tz_abbr if unset in 'parsed' but set in 'now'.
510584db6f3SDerick Rethans  *
511584db6f3SDerick Rethans  * It duplicates tz_info if unset in 'parsed', but set in 'now' unless
512584db6f3SDerick Rethans  * TIMELIB_NO_CLONE is passed, in which case only the pointer in 'parsed' is
513584db6f3SDerick Rethans  * set to 'now'.
514584db6f3SDerick Rethans  *
515584db6f3SDerick Rethans  * If the option TIMELIB_OVERRIDE_TIME is passed and the parsed date/time has
516584db6f3SDerick Rethans  * no time portion, the function will ignore the time aspect in 'now' and
517584db6f3SDerick Rethans  * instead fill it with zeros.
518584db6f3SDerick Rethans  */
5194fb4cac6SDerick Rethans void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options);
520584db6f3SDerick Rethans 
521584db6f3SDerick Rethans /* Tries to convert a time zone abbreviation, gmtoffset and/or isdst flag
522584db6f3SDerick Rethans  * combination to a time zone identifier.
523584db6f3SDerick Rethans  *
524584db6f3SDerick Rethans  * If 'abbr' is either 'utc' or 'gmt' (case insensitve) then "UTC" is
525584db6f3SDerick Rethans  * returned.
526584db6f3SDerick Rethans  *
527584db6f3SDerick Rethans  * It first uses the data in the timezonemap.h file to find a matching
528584db6f3SDerick Rethans  * abbreviation/GMT offset combination. If not found, it uses the data in
529584db6f3SDerick Rethans  * fallbackmap.h to match only the GMT offset/isdst flag to try to find a
530584db6f3SDerick Rethans  * match. If nothing is found, NULL is returned.
531584db6f3SDerick Rethans  *
532584db6f3SDerick Rethans  * The returned char* is not duplicated, and should not be freed.
533584db6f3SDerick Rethans  */
534fab5cbabSDerick Rethans char *timelib_timezone_id_from_abbr(const char *abbr, timelib_long gmtoffset, int isdst);
535584db6f3SDerick Rethans 
536584db6f3SDerick Rethans /* Returns an array of known time zone abbreviations
537584db6f3SDerick Rethans  *
538584db6f3SDerick Rethans  * This file is generated from the time zone database through the
539584db6f3SDerick Rethans  * gettzmapping.php scripts, which requires that an up-to-date time zone
540584db6f3SDerick Rethans  * database is used with the PHP binary that runs the script.
541584db6f3SDerick Rethans  *
542584db6f3SDerick Rethans  * Each item in the returned list contains the abbreviation, a flag whether
543584db6f3SDerick Rethans  * it's an abbreviation used with DST, the UTC offset in seconds, and the name
544584db6f3SDerick Rethans  * of the time zone identifier that this abbreviation belongs to.
545584db6f3SDerick Rethans  *
546584db6f3SDerick Rethans  * The order for each specific abbreviation is controlled through the
547584db6f3SDerick Rethans  * preference list in the gettzmapping.php script. Time zones that match the
548584db6f3SDerick Rethans  * pattern ±\d{2,4} are excluded
549584db6f3SDerick Rethans  */
55074dfa9f0SDerick Rethans const timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void);
551584db6f3SDerick Rethans 
552584db6f3SDerick Rethans /**
553584db6f3SDerick Rethans  * DEPRECATED, but still used by PHP.
554584db6f3SDerick Rethans  */
555584db6f3SDerick Rethans 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);
5564fb4cac6SDerick Rethans 
5572047fa85SDerick Rethans /* From parse_iso_intervals.re */
558584db6f3SDerick Rethans 
559584db6f3SDerick Rethans /**
560584db6f3SDerick Rethans  * Parses a subset of an ISO 8601 intervals specification string into its
561584db6f3SDerick Rethans  * constituent parts.
562584db6f3SDerick Rethans  *
563584db6f3SDerick Rethans  * If the **errors points to a timelib_error_container variable, warnings
564584db6f3SDerick Rethans  * and errors will be recorded. You are responsible for freeing the stored
565584db6f3SDerick Rethans  * information with timelib_error_container_dtor(). To see whether errors have
5669c608bd1SDerick Rethans  * occurred, inspect errors->errors_count. To see whether warnings have occurred,
567584db6f3SDerick Rethans  * inspect errors->warnings_count.
568584db6f3SDerick Rethans  */
569fab5cbabSDerick Rethans void timelib_strtointerval(char *s, size_t len,
570cdd2b8a7SDerick Rethans                            timelib_time **begin, timelib_time **end,
57109340ea9SDerick Rethans                            timelib_rel_time **period, int *recurrences,
57209340ea9SDerick Rethans                            timelib_error_container **errors);
5732047fa85SDerick Rethans 
5742047fa85SDerick Rethans 
5754fb4cac6SDerick Rethans /* From tm2unixtime.c */
576584db6f3SDerick Rethans 
577584db6f3SDerick Rethans /**
578584db6f3SDerick Rethans  * Uses the y/m/d/h/i/s fields to calculate and store the equivalent timestamp
579584db6f3SDerick Rethans  * in the sse field.
580584db6f3SDerick Rethans  *
581584db6f3SDerick Rethans  * It uses the time zone information associated with 'time' to account for the
582584db6f3SDerick Rethans  * right UTC offset and/or DST rules. You can associate time zone information
583584db6f3SDerick Rethans  * with the timelib_set_timezone_* functions (see below).
584584db6f3SDerick Rethans  *
585584db6f3SDerick Rethans  * If the type is 'TIMELIB_ZONETYPE_ID' and there is no associated tzinfo, it
586584db6f3SDerick Rethans  * will use the second argument 'tzi' to provide the rules necessary to
587584db6f3SDerick Rethans  * calculate the right timestamp.
588584db6f3SDerick Rethans  */
5894fb4cac6SDerick Rethans void timelib_update_ts(timelib_time* time, timelib_tzinfo* tzi);
590584db6f3SDerick Rethans 
591584db6f3SDerick Rethans /**
592584db6f3SDerick Rethans  * Takes the information from the y/m/d/h/i/s fields and makes sure their
593584db6f3SDerick Rethans  * values are in the right range.
594584db6f3SDerick Rethans  *
595584db6f3SDerick Rethans  * If a value under- or overflows it will adjust the larger measure up (or
596584db6f3SDerick Rethans  * down). It also takes into account leap days.
597584db6f3SDerick Rethans  */
5985b2ce47fSDerick Rethans void timelib_do_normalize(timelib_time *base);
599584db6f3SDerick Rethans 
600584db6f3SDerick Rethans /**
601584db6f3SDerick Rethans  * Takes the information from the y/m/d/h/i/s fields of 'rt' and makes sure
602584db6f3SDerick Rethans  * their values are in the right range.
603584db6f3SDerick Rethans  *
604584db6f3SDerick Rethans  * If a value under- or overflows it will adjust the larger measure up (or
605584db6f3SDerick Rethans  * down). As this function operates on a *relative date/time*, it also takes
606584db6f3SDerick Rethans  * into account leap days and correctly accounts for the difference depending
607584db6f3SDerick Rethans  * on the base date/time in 'base'.
608584db6f3SDerick Rethans  */
6092047fa85SDerick Rethans void timelib_do_rel_normalize(timelib_time *base, timelib_rel_time *rt);
6104fb4cac6SDerick Rethans 
6114fb4cac6SDerick Rethans /* From unixtime2tm.c */
612584db6f3SDerick Rethans 
613584db6f3SDerick Rethans /**
614584db6f3SDerick Rethans  * Takes the unix timestamp in seconds from 'ts' and populates the y/m/d/h/i/s
615584db6f3SDerick Rethans  * fields of 'tm' without taking time zones into account
616584db6f3SDerick Rethans  */
6174fb4cac6SDerick Rethans void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts);
618584db6f3SDerick Rethans 
619584db6f3SDerick Rethans /**
620584db6f3SDerick Rethans  * Takes the Unix timestamp from 'ts', and calculates the y/m/d/h/i/s fields
621584db6f3SDerick Rethans  * according to the time zone information attached to 'tm'.
622584db6f3SDerick Rethans  */
6237b581f6dSDerick Rethans void timelib_unixtime2local(timelib_time *tm, timelib_sll ts);
624584db6f3SDerick Rethans 
625584db6f3SDerick Rethans /**
626584db6f3SDerick Rethans  * Takes the Unix timestamp stored in 'tm', and calculates the y/m/d/h/i/s
627584db6f3SDerick Rethans  * fields according to the time zone information attached to 'tm'.
628584db6f3SDerick Rethans  */
629e6c1ff25SDerick Rethans void timelib_update_from_sse(timelib_time *tm);
630584db6f3SDerick Rethans 
631584db6f3SDerick Rethans /**
632584db6f3SDerick Rethans  * Attaches the UTC offset as time zone information to 't'.
633584db6f3SDerick Rethans  *
634584db6f3SDerick Rethans  * 'utc_offset' is in seconds East of UTC.
635584db6f3SDerick Rethans  */
63622dba2f5SDerick Rethans void timelib_set_timezone_from_offset(timelib_time *t, timelib_sll utc_offset);
637584db6f3SDerick Rethans 
638584db6f3SDerick Rethans /**
639584db6f3SDerick Rethans  * Attaches the information from 'abbr_info' as time zone information to 't'.
640584db6f3SDerick Rethans  *
641584db6f3SDerick Rethans  * The timelib_abbr_info struct contains an abbreviation ('abbr') which string
642584db6f3SDerick Rethans  * value is duplicated, as well as a 'utc_offset' and 'dst' flag. It only
643584db6f3SDerick Rethans  * supports a 'dst' change over of 1 hour.
644584db6f3SDerick Rethans  */
64522dba2f5SDerick Rethans void timelib_set_timezone_from_abbr(timelib_time *t, timelib_abbr_info abbr_info);
646584db6f3SDerick Rethans 
647584db6f3SDerick Rethans /**
648584db6f3SDerick Rethans  * Attaches the time zone information in 'tz' to to 't'.
649584db6f3SDerick Rethans  *
650584db6f3SDerick Rethans  * It fetches the right UTC offset that is currently stored in the time
651584db6f3SDerick Rethans  * stamp field in 't' ('sse'), and assigns that to the 'z' field and 'dst'
652584db6f3SDerick Rethans  * field (whether DST is in effect at the time). It also sets the current
653aae5907cSDerick Rethans  * abbreviation to the 'tz_addr' field, making sure that if a value was already
654584db6f3SDerick Rethans  * set it was freed.
655584db6f3SDerick Rethans  *
656584db6f3SDerick Rethans  * The time zone information in 'tz' is *not* duplicated into the 't' field so
657584db6f3SDerick Rethans  * it should not be freed until all timelib_time* variables have been freed as
658584db6f3SDerick Rethans  * well.
659584db6f3SDerick Rethans  */
6604fb4cac6SDerick Rethans void timelib_set_timezone(timelib_time *t, timelib_tzinfo *tz);
6614fb4cac6SDerick Rethans 
6624fb4cac6SDerick Rethans /* From parse_tz.c */
663584db6f3SDerick Rethans 
664584db6f3SDerick Rethans /**
665584db6f3SDerick Rethans  * Returns whether the time zone ID 'timezone' is available in the time zone
666584db6f3SDerick Rethans  * database as pointed to be 'tzdb'.
667584db6f3SDerick Rethans  */
66874dfa9f0SDerick Rethans int timelib_timezone_id_is_valid(char *timezone, const timelib_tzdb *tzdb);
669584db6f3SDerick Rethans 
670584db6f3SDerick Rethans /**
671584db6f3SDerick Rethans  * Converts the binary stored time zone information from 'tzdb' for the time
672584db6f3SDerick Rethans  * zone 'timeozne' into a structure the library can use for calculations.
673584db6f3SDerick Rethans  *
674584db6f3SDerick Rethans  * The function can be used on both timelib_builtin_db as well as a time zone
675584db6f3SDerick Rethans  * db as opened by timelib_zoneinfo.
676584db6f3SDerick Rethans  * The function will return null upon failure, and also set an error code
677584db6f3SDerick Rethans  * through 'error_code'. 'error_code' must not be a null pointer. The error
678584db6f3SDerick Rethans  * code is one of the TIMELIB_ERROR_* constants as listed above. These error
679584db6f3SDerick Rethans  * constants can be converted into a string by timelib_get_error_message.
680584db6f3SDerick Rethans  *
681584db6f3SDerick Rethans  * This function allocates memory for the new time zone structure, which must
682584db6f3SDerick Rethans  * be freed after use. Although it is recommended that a cache of each used
683584db6f3SDerick Rethans  * time zone is kept.
684584db6f3SDerick Rethans  */
685584db6f3SDerick Rethans timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb, int *error_code);
686584db6f3SDerick Rethans 
687584db6f3SDerick Rethans /**
688584db6f3SDerick Rethans  * Frees up the resources allocated by 'timelib_parse_tzfile'.
689584db6f3SDerick Rethans  */
690584db6f3SDerick Rethans void timelib_tzinfo_dtor(timelib_tzinfo *tz);
691584db6f3SDerick Rethans 
692584db6f3SDerick Rethans /**
693584db6f3SDerick Rethans  * Deep-clones a timelib_tzinfo structure.
694584db6f3SDerick Rethans  *
695584db6f3SDerick Rethans  * This allocates resources that need to be freed with 'timelib_tzinfo_dtor'
696584db6f3SDerick Rethans  */
697584db6f3SDerick Rethans timelib_tzinfo* timelib_tzinfo_clone(timelib_tzinfo *tz);
698584db6f3SDerick Rethans 
699584db6f3SDerick Rethans /**
700584db6f3SDerick Rethans  * Returns whether DST is active with time zone 'tz' for the time stamp 'ts'.
701584db6f3SDerick Rethans  *
702584db6f3SDerick Rethans  * Returns 0 if DST is not active, 1 if DST is active, or -1 if no transitions
703584db6f3SDerick Rethans  * were available through 'tz'.
704584db6f3SDerick Rethans  */
7054fb4cac6SDerick Rethans int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz);
706584db6f3SDerick Rethans 
707584db6f3SDerick Rethans /**
708584db6f3SDerick Rethans  * Returns offset information with time zone 'tz' for the time stamp 'ts'.
709584db6f3SDerick Rethans  *
710584db6f3SDerick Rethans  * The returned information contains: the offset in seconds East of UTC (in
711584db6f3SDerick Rethans  * 'offset'), whether DST is active ('is_dst'), what the current time zone
712584db6f3SDerick Rethans  * abbreviation is ('abbr') and the transition time that got to this state (in
71309340ea9SDerick Rethans  * 'transition_time');
714584db6f3SDerick Rethans  */
7154fb4cac6SDerick Rethans timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz);
716584db6f3SDerick Rethans 
717584db6f3SDerick Rethans /**
718584db6f3SDerick Rethans  * Returns the UTC offset currently applicable for the information stored in 't'.
719584db6f3SDerick Rethans  *
720584db6f3SDerick Rethans  * The value returned is the UTC offset in seconds East.
721584db6f3SDerick Rethans  */
72288268c6bSDerick Rethans timelib_sll timelib_get_current_offset(timelib_time *t);
723584db6f3SDerick Rethans 
724584db6f3SDerick Rethans /**
725584db6f3SDerick Rethans  * Displays debugging information about the time zone information in 'tz'.
726584db6f3SDerick Rethans  */
727ca167760SDerick Rethans void timelib_dump_tzinfo(timelib_tzinfo *tz);
728584db6f3SDerick Rethans 
729584db6f3SDerick Rethans /**
730584db6f3SDerick Rethans  * Returns a pointer to the built-in time zone database.
731584db6f3SDerick Rethans  *
732584db6f3SDerick Rethans  * You must *not* free the returned pointer as it is part of the text segment.
733584db6f3SDerick Rethans  */
73474dfa9f0SDerick Rethans const timelib_tzdb *timelib_builtin_db(void);
735584db6f3SDerick Rethans 
736584db6f3SDerick Rethans /**
737584db6f3SDerick Rethans  * Returns a pointer to the start of an array containing a list of timezone identifiers.
738584db6f3SDerick Rethans  *
739584db6f3SDerick Rethans  * The amount of entries in the array is returned through the 'count' OUT parameter.
740584db6f3SDerick Rethans  *
741584db6f3SDerick Rethans  * Each entry contains the time zone ID ('id' field), and the position within the time zone
742584db6f3SDerick Rethans  * information ('pos' field). The pos field should not be used.
743584db6f3SDerick Rethans  */
7445feb5396SDerick Rethans const timelib_tzdb_index_entry *timelib_timezone_identifiers_list(const timelib_tzdb *tzdb, int *count);
745584db6f3SDerick Rethans 
746584db6f3SDerick Rethans /* From parse_zoneinfo.c */
747584db6f3SDerick Rethans 
748584db6f3SDerick Rethans /**
749584db6f3SDerick Rethans  * Scans the directory and subdirectories of 'directory' for valid time zone files and builds
750584db6f3SDerick Rethans  * a time zone database out of these files.
751584db6f3SDerick Rethans  *
752584db6f3SDerick Rethans  * Typically, the directory should point to '/usr/share/zoneinfo'.
753584db6f3SDerick Rethans  *
754584db6f3SDerick Rethans  * Unlike 'timelib_builtin_db', the return value of this function must be freed
755584db6f3SDerick Rethans  * with the 'timelib_zoneinfo_dtor' function.
756584db6f3SDerick Rethans  */
757584db6f3SDerick Rethans timelib_tzdb *timelib_zoneinfo(char *directory);
758584db6f3SDerick Rethans 
759584db6f3SDerick Rethans /**
760584db6f3SDerick Rethans  * Frees up the resources as created through 'timelib_zoneinfo'.
761584db6f3SDerick Rethans  *
762584db6f3SDerick Rethans  * This function must be used to free up all the resources that have been
763584db6f3SDerick Rethans  * allocated while calling 'timelib_zoneinfo'.
764584db6f3SDerick Rethans  */
765584db6f3SDerick Rethans void timelib_zoneinfo_dtor(timelib_tzdb *tzdb);
7664fb4cac6SDerick Rethans 
7674ad939beSDerick Rethans /* From timelib.c */
7684fb4cac6SDerick Rethans 
769584db6f3SDerick Rethans /**
770584db6f3SDerick Rethans  * Returns a static string containing an error message belonging to a specific
771584db6f3SDerick Rethans  * error code.
772584db6f3SDerick Rethans  */
773584db6f3SDerick Rethans const char *timelib_get_error_message(int error_code);
774584db6f3SDerick Rethans 
775584db6f3SDerick Rethans /**
776584db6f3SDerick Rethans  * Allocates resources for the relative time structure.
777584db6f3SDerick Rethans  *
778584db6f3SDerick Rethans  * Must be freed with 'timelib_rel_time_dtor'.
779584db6f3SDerick Rethans  */
7802047fa85SDerick Rethans timelib_rel_time* timelib_rel_time_ctor(void);
781584db6f3SDerick Rethans 
782584db6f3SDerick Rethans /**
783584db6f3SDerick Rethans  * Frees up the resources as allocated through 'timelib_rel_time_ctor'.
784584db6f3SDerick Rethans  */
7852047fa85SDerick Rethans void timelib_rel_time_dtor(timelib_rel_time* t);
786584db6f3SDerick Rethans 
787584db6f3SDerick Rethans /**
788584db6f3SDerick Rethans  * Creates a new timelib_rel_time resource and copies over the information
789584db6f3SDerick Rethans  * from 'tz'.
790584db6f3SDerick Rethans  *
791584db6f3SDerick Rethans  * Must be freed with 'timelib_rel_time_dtor'.
792584db6f3SDerick Rethans  */
7938c5274f4SDerick Rethans timelib_rel_time* timelib_rel_time_clone(timelib_rel_time *tz);
7942047fa85SDerick Rethans 
795584db6f3SDerick Rethans /**
796584db6f3SDerick Rethans  * Allocates resources for the time structure.
797584db6f3SDerick Rethans  *
798584db6f3SDerick Rethans  * Must be freed with 'timelib_time_dtor'.
799584db6f3SDerick Rethans  */
800bffb8c40SJani Taskinen timelib_time* timelib_time_ctor(void);
801584db6f3SDerick Rethans 
802584db6f3SDerick Rethans /**
803584db6f3SDerick Rethans  * Frees up the resources as allocated through 'timelib_time_ctor'.
804584db6f3SDerick Rethans  */
8054fb4cac6SDerick Rethans void timelib_time_dtor(timelib_time* t);
806584db6f3SDerick Rethans 
807584db6f3SDerick Rethans /**
808584db6f3SDerick Rethans  * Creates a new timelib_time resource and copies over the information
809584db6f3SDerick Rethans  * from 'orig'.
810584db6f3SDerick Rethans  *
811584db6f3SDerick Rethans  * Must be freed with 'timelib_time_dtor'.
812584db6f3SDerick Rethans  */
813bd184cc5SDerick Rethans timelib_time* timelib_time_clone(timelib_time* orig);
814584db6f3SDerick Rethans 
815584db6f3SDerick Rethans /**
816584db6f3SDerick Rethans  * Compares two timelib_time structures and returns which one is earlier in
817584db6f3SDerick Rethans  * time.
818584db6f3SDerick Rethans  *
819584db6f3SDerick Rethans  * To decide which comes earlier it uses the 'sse' (Seconds Since Epoch) and
820584db6f3SDerick Rethans  * 'us' (microseconds) fields.
821584db6f3SDerick Rethans  *
822584db6f3SDerick Rethans  * Returns -1 if t1 < t2, 0 if t1 == t2, and -1 if t1 > t2.
823584db6f3SDerick Rethans  */
824822ca452SDerick Rethans int timelib_time_compare(timelib_time *t1, timelib_time *t2);
8254fb4cac6SDerick Rethans 
826584db6f3SDerick Rethans /**
827584db6f3SDerick Rethans  * Allocates resources for the time offset structure.
828584db6f3SDerick Rethans  *
829584db6f3SDerick Rethans  * Must be freed with 'timelib_time_offset_dtor'.
830584db6f3SDerick Rethans  */
831bffb8c40SJani Taskinen timelib_time_offset* timelib_time_offset_ctor(void);
832584db6f3SDerick Rethans 
833584db6f3SDerick Rethans /**
834584db6f3SDerick Rethans  * Frees up the resources as allocated through 'timelib_time_offset_ctor'.
835584db6f3SDerick Rethans  */
8364fb4cac6SDerick Rethans void timelib_time_offset_dtor(timelib_time_offset* t);
8374fb4cac6SDerick Rethans 
838584db6f3SDerick Rethans /**
839584db6f3SDerick Rethans  * Frees up the resources allocated while converting strings to timelib_time
840584db6f3SDerick Rethans  * structures with the timelib_strtotime and timelib_strtointerval functions.
841584db6f3SDerick Rethans  */
8424043f77eSDerick Rethans void timelib_error_container_dtor(timelib_error_container *errors);
8434043f77eSDerick Rethans 
844584db6f3SDerick Rethans /**
845584db6f3SDerick Rethans  * Converts the 'sse' value of 'd' to a timelib_long type.
846584db6f3SDerick Rethans  *
847584db6f3SDerick Rethans  * If the value fits in the TIMELIB_LONG_MIN and TIMELIB_LONG_MAX range, the
848584db6f3SDerick Rethans  * value is cast to (timelib_long) and returned. If *error is not a NULL
849584db6f3SDerick Rethans  * pointer, it will be set to 0.
850584db6f3SDerick Rethans  *
851584db6f3SDerick Rethans  * If the value does *not* fit in the range, the function returns 0 and if
852584db6f3SDerick Rethans  * *error is not a NULL pointer, it will be set to 1.
853584db6f3SDerick Rethans  *
854584db6f3SDerick Rethans  * timelib_long is a 32 bit signed long integer on 32 bit platforms, and a 64
855584db6f3SDerick Rethans  * bit signed long long integer on 64 bit platforms. In other words, it makes
856584db6f3SDerick Rethans  * sure that the value in 'sse' (which is always a signed long long 64 bit
857584db6f3SDerick Rethans  * integer) can be used safely outside of the library.
858584db6f3SDerick Rethans  */
859fab5cbabSDerick Rethans timelib_long timelib_date_to_int(timelib_time *d, int *error);
860584db6f3SDerick Rethans 
861584db6f3SDerick Rethans /**
862584db6f3SDerick Rethans  * Displays debugging information about the date/time information stored in 'd'.
863584db6f3SDerick Rethans  *
864584db6f3SDerick Rethans  * 'options' is a bit field, where:
865584db6f3SDerick Rethans  * - 1 controls whether the relative time portion is shown.
866584db6f3SDerick Rethans  * - 2 controls whether the zone type is shown.
867584db6f3SDerick Rethans  */
8684fb4cac6SDerick Rethans void timelib_dump_date(timelib_time *d, int options);
869584db6f3SDerick Rethans 
870584db6f3SDerick Rethans /**
871584db6f3SDerick Rethans  * Displays debugging information about the relative time information stored
872584db6f3SDerick Rethans  * in 'd'.
873584db6f3SDerick Rethans  */
8742047fa85SDerick Rethans void timelib_dump_rel_time(timelib_rel_time *d);
8754fb4cac6SDerick Rethans 
876584db6f3SDerick Rethans /**
877584db6f3SDerick Rethans  * Converts a decimal hour into hour/min/sec components
878584db6f3SDerick Rethans  */
8797b581f6dSDerick Rethans void timelib_decimal_hour_to_hms(double h, int *hour, int *min, int *sec);
880584db6f3SDerick Rethans 
881584db6f3SDerick Rethans /**
882584db6f3SDerick Rethans  * Converts hour/min/sec values into a decimal hour
883584db6f3SDerick Rethans  */
884584db6f3SDerick Rethans void timelib_hms_to_decimal_hour(int hour, int min, int sec, double *h);
8857b581f6dSDerick Rethans 
8867b581f6dSDerick Rethans /* from astro.c */
887584db6f3SDerick Rethans 
888584db6f3SDerick Rethans /**
889584db6f3SDerick Rethans  * Converts the Unix Epoch time stamp 'ts' to a Julian Day
890584db6f3SDerick Rethans  *
891584db6f3SDerick Rethans  * The value returned is the number of whole days since -4714-11-24T12:00:00 UTC
892584db6f3SDerick Rethans  * (in the proleptic Gregorian calendar):
893584db6f3SDerick Rethans  * https://en.wikipedia.org/wiki/Julian_day
894584db6f3SDerick Rethans  */
895584db6f3SDerick Rethans double timelib_ts_to_julianday(timelib_sll ts);
896584db6f3SDerick Rethans 
897584db6f3SDerick Rethans /**
898584db6f3SDerick Rethans  * Converts the Unix Epoch time stamp 'ts' to the J2000 epoch
899584db6f3SDerick Rethans  *
900584db6f3SDerick Rethans  * The value returned is the number of whole days since 2000-01-01T12:00:00
901584db6f3SDerick Rethans  * UTC: https://en.wikipedia.org/wiki/Epoch_(astronomy)#Julian_years_and_J2000
902584db6f3SDerick Rethans  */
903584db6f3SDerick Rethans double timelib_ts_to_j2000(timelib_sll ts);
904584db6f3SDerick Rethans 
905584db6f3SDerick Rethans /**
906584db6f3SDerick Rethans  * Calculates when the Sun is above a certain latitude.
907584db6f3SDerick Rethans  *
908584db6f3SDerick Rethans  * Parameters:
909584db6f3SDerick Rethans  * - time: A timelib_time time describing that needs to specific midnight for a
910584db6f3SDerick Rethans  *         specific day.
911584db6f3SDerick Rethans  * - lon: The longitude of the observer (East positive, West negative).
912584db6f3SDerick Rethans  * - lat: The latitude of the observer (North positive, South negative).
913584db6f3SDerick Rethans  * - altit: The altitude. Set to -35/60 for rise/set, -6 for civil twilight,
914584db6f3SDerick Rethans  *          -12 for nautical, and -18 for astronomical twilight.
915584db6f3SDerick Rethans  * - upper_limb: set to non-zero for rise/set calculations, and 0 for twilight
916584db6f3SDerick Rethans  *               calculations.
917584db6f3SDerick Rethans  *
918584db6f3SDerick Rethans  * Out Parameters:
919584db6f3SDerick Rethans  * - h_rise: The decimal hour when the Sun rises
920584db6f3SDerick Rethans  * - h_set: The decimal hour when the Sun sets
921584db6f3SDerick Rethans  * - ts_rise: The Unix timestamp of the Sun rising
922584db6f3SDerick Rethans  * - ts_set: The Unix timestamp of the Sun setting
923584db6f3SDerick Rethans  * - ts_transit: The Unix timestmap of the Sun transitting through South
924584db6f3SDerick Rethans  *
925584db6f3SDerick Rethans  * Return Values:
926584db6f3SDerick Rethans  * - 0: The Sun rises and sets.
927584db6f3SDerick Rethans  * - +1: The Sun is always above the horizon. (ts_rise is set to ts_transit -
928584db6f3SDerick Rethans  *       (12 * 3600); ts_set is set to ts_transit + (12 * 3600).
929584db6f3SDerick Rethans  * - -1: The Sun is awlays below the horizon. (ts_rise and ts_set are set
930584db6f3SDerick Rethans  *       to ts_transit)
931584db6f3SDerick Rethans  */
93288268c6bSDerick Rethans 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);
9337b581f6dSDerick Rethans 
9342047fa85SDerick Rethans /* from interval.c */
935584db6f3SDerick Rethans 
936584db6f3SDerick Rethans /**
937584db6f3SDerick Rethans  * Calculates the difference between two times
938584db6f3SDerick Rethans  *
939584db6f3SDerick Rethans  * The result is a timelib_rel_time structure that describes how you can
940584db6f3SDerick Rethans  * convert from 'one' to 'two' with 'timelib_add'. This does *not* necessarily
941584db6f3SDerick Rethans  * mean that you can go from 'two' to 'one' by using 'timelib_sub' due to the
942584db6f3SDerick Rethans  * way months and days are calculated.
943584db6f3SDerick Rethans  */
9442047fa85SDerick Rethans timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two);
945584db6f3SDerick Rethans 
946584db6f3SDerick Rethans /**
947584db6f3SDerick Rethans  * Adds the relative time information 'interval' to the base time 't'.
948584db6f3SDerick Rethans  *
949584db6f3SDerick Rethans  * This can be a relative time as created by 'timelib_diff', but also by more
950584db6f3SDerick Rethans  * complex statements such as "next workday".
951584db6f3SDerick Rethans  */
9525d0c5261SDerick Rethans timelib_time *timelib_add(timelib_time *t, timelib_rel_time *interval);
953584db6f3SDerick Rethans 
954584db6f3SDerick Rethans /**
955584db6f3SDerick Rethans  * Subtracts the relative time information 'interval' to the base time 't'.
956584db6f3SDerick Rethans  *
957584db6f3SDerick Rethans  * This can be a relative time as created by 'timelib_diff'. Unlike with
958584db6f3SDerick Rethans  * 'timelib_add', this does not support more complex statements such as "next
959584db6f3SDerick Rethans  * workday".
960584db6f3SDerick Rethans  */
9615d0c5261SDerick Rethans timelib_time *timelib_sub(timelib_time *t, timelib_rel_time *interval);
9622047fa85SDerick Rethans 
963584db6f3SDerick Rethans #ifdef __cplusplus
964584db6f3SDerick Rethans } /* extern "C" */
965584db6f3SDerick Rethans #endif
966584db6f3SDerick Rethans 
967a736f99eSfoobar #endif
968