summaryrefslogtreecommitdiff
path: root/ext/date/lib/timelib.h
diff options
context:
space:
mode:
authorDerick Rethans <github@derickrethans.nl>2017-08-15 15:06:18 +0100
committerDerick Rethans <github@derickrethans.nl>2017-08-15 15:06:18 +0100
commit584db6f38fcac3e5e1ca4c770d3aacfff09ee371 (patch)
tree5223b28c60a05d7870ea2d76b7bdbd84bcf0b2d8 /ext/date/lib/timelib.h
parent3bc12268041bdeec9941c99f08b71620f7572eb0 (diff)
downloadphp-git-584db6f38fcac3e5e1ca4c770d3aacfff09ee371.tar.gz
Merged PHP-7.0 by hand due to conflicts.
Diffstat (limited to 'ext/date/lib/timelib.h')
-rw-r--r--ext/date/lib/timelib.h801
1 files changed, 761 insertions, 40 deletions
diff --git a/ext/date/lib/timelib.h b/ext/date/lib/timelib.h
index e58a92a5e6..a3450f4f9a 100644
--- a/ext/date/lib/timelib.h
+++ b/ext/date/lib/timelib.h
@@ -25,11 +25,283 @@
#ifndef __TIMELIB_H__
#define __TIMELIB_H__
-#include "timelib_structs.h"
-#if HAVE_LIMITS_H
+#ifdef HAVE_TIMELIB_CONFIG_H
+# include "timelib_config.h"
+#endif
+
+#include <stdlib.h>
#include <limits.h>
+#include <inttypes.h>
+
+# ifndef HAVE_INT32_T
+# if SIZEOF_INT == 4
+typedef int int32_t;
+# elif SIZEOF_LONG == 4
+typedef long int int32_t;
+# endif
+# endif
+
+# ifndef HAVE_UINT32_T
+# if SIZEOF_INT == 4
+typedef unsigned int uint32_t;
+# elif SIZEOF_LONG == 4
+typedef unsigned long int uint32_t;
+# endif
+# endif
+
+#ifdef _WIN32
+# if _MSC_VER >= 1600
+# include <stdint.h>
+# endif
+# ifndef SIZEOF_INT
+# define SIZEOF_INT 4
+# endif
+# ifndef SIZEOF_LONG
+# define SIZEOF_LONG 4
+# endif
+# ifndef int32_t
+typedef __int32 int32_t;
+# endif
+# ifndef uint32_t
+typedef unsigned __int32 uint32_t;
+# endif
+# ifndef int64_t
+typedef __int64 int64_t;
+# endif
+# ifndef uint64_t
+typedef unsigned __int64 uint64_t;
+# endif
+# ifndef PRId32
+# define PRId32 "I32d"
+# endif
+# ifndef PRIu32
+# define PRIu32 "I32u"
+# endif
+# ifndef PRId64
+# define PRId64 "I64d"
+# endif
+# ifndef PRIu64
+# define PRIu64 "I64u"
+# endif
+# ifndef INT32_MAX
+#define INT32_MAX _I32_MAX
+# endif
+# ifndef INT32_MIN
+#define INT32_MIN ((int32_t)_I32_MIN)
+# endif
+# ifndef UINT32_MAX
+#define UINT32_MAX _UI32_MAX
+# endif
+# ifndef INT64_MIN
+#define INT64_MIN ((int64_t)_I64_MIN)
+# endif
+# ifndef INT64_MAX
+#define INT64_MAX _I64_MAX
+# endif
+# ifndef UINT64_MAX
+#define UINT64_MAX _UI64_MAX
+# endif
+#endif
+
+#if (defined(__x86_64__) || defined(__LP64__) || defined(_LP64) || defined(_WIN64)) && !defined(TIMELIB_FORCE_LONG32)
+typedef int64_t timelib_long;
+typedef uint64_t timelib_ulong;
+# define TIMELIB_LONG_MAX INT64_MAX
+# define TIMELIB_LONG_MIN INT64_MIN
+# define TIMELIB_ULONG_MAX UINT64_MAX
+# define TIMELIB_LONG_FMT "%" PRId64
+# define TIMELIB_ULONG_FMT "%" PRIu64
+#else
+typedef int32_t timelib_long;
+typedef uint32_t timelib_ulong;
+# define TIMELIB_LONG_MAX INT32_MAX
+# define TIMELIB_LONG_MIN INT32_MIN
+# define TIMELIB_ULONG_MAX UINT32_MAX
+# define TIMELIB_LONG_FMT "%" PRId32
+# define TIMELIB_ULONG_FMT "%" PRIu32
#endif
+#if defined(_MSC_VER)
+typedef uint64_t timelib_ull;
+typedef int64_t timelib_sll;
+# define TIMELIB_LL_CONST(n) n ## i64
+#else
+typedef unsigned long long timelib_ull;
+typedef signed long long timelib_sll;
+# define TIMELIB_LL_CONST(n) n ## ll
+#endif
+
+typedef struct ttinfo ttinfo;
+typedef struct tlinfo tlinfo;
+
+typedef struct tlocinfo
+{
+ char country_code[3];
+ double latitude;
+ double longitude;
+ char *comments;
+} tlocinfo;
+
+typedef struct timelib_tzinfo
+{
+ char *name;
+ struct {
+ uint32_t ttisgmtcnt;
+ uint32_t ttisstdcnt;
+ uint32_t leapcnt;
+ uint32_t timecnt;
+ uint32_t typecnt;
+ uint32_t charcnt;
+ } bit32;
+ struct {
+ uint64_t ttisgmtcnt;
+ uint64_t ttisstdcnt;
+ uint64_t leapcnt;
+ uint64_t timecnt;
+ uint64_t typecnt;
+ uint64_t charcnt;
+ } bit64;
+
+ int32_t *trans;
+ unsigned char *trans_idx;
+
+ ttinfo *type;
+ char *timezone_abbr;
+
+ tlinfo *leap_times;
+ unsigned char bc;
+ tlocinfo location;
+} timelib_tzinfo;
+
+typedef struct timelib_rel_time {
+ timelib_sll y, m, d; /* Years, Months and Days */
+ timelib_sll h, i, s; /* Hours, mInutes and Seconds */
+ timelib_sll us; /* Microseconds */
+
+ int weekday; /* Stores the day in 'next monday' */
+ int weekday_behavior; /* 0: the current day should *not* be counted when advancing forwards; 1: the current day *should* be counted */
+
+ int first_last_day_of;
+ int invert; /* Whether the difference should be inverted */
+ timelib_sll days; /* Contains the number of *days*, instead of Y-M-D differences */
+
+ struct {
+ unsigned int type;
+ timelib_sll amount;
+ } special;
+
+ unsigned int have_weekday_relative, have_special_relative;
+} timelib_rel_time;
+
+typedef struct timelib_time_offset {
+ int32_t offset;
+ unsigned int leap_secs;
+ unsigned int is_dst;
+ char *abbr;
+ timelib_sll transition_time;
+} timelib_time_offset;
+
+typedef struct timelib_time {
+ timelib_sll y, m, d; /* Year, Month, Day */
+ timelib_sll h, i, s; /* Hour, mInute, Second */
+ timelib_sll us; /* Microseconds */
+ int z; /* UTC offset in seconds */
+ char *tz_abbr; /* Timezone abbreviation (display only) */
+ timelib_tzinfo *tz_info; /* Timezone structure */
+ signed int dst; /* Flag if we were parsing a DST zone */
+ timelib_rel_time relative;
+
+ timelib_sll sse; /* Seconds since epoch */
+
+ unsigned int have_time, have_date, have_zone, have_relative, have_weeknr_day;
+
+ unsigned int sse_uptodate; /* !0 if the sse member is up to date with the date/time members */
+ unsigned int tim_uptodate; /* !0 if the date/time members are up to date with the sse member */
+ unsigned int is_localtime; /* 1 if the current struct represents localtime, 0 if it is in GMT */
+ unsigned int zone_type; /* 1 time offset,
+ * 3 TimeZone identifier,
+ * 2 TimeZone abbreviation */
+} timelib_time;
+
+typedef struct timelib_abbr_info {
+ timelib_sll utc_offset;
+ char *abbr;
+ int dst;
+} timelib_abbr_info;
+
+#define TIMELIB_WARN_MASK 0x1ff
+#define TIMELIB_ERR_MASK 0x2ff
+
+#define TIMELIB_WARN_DOUBLE_TZ 0x101
+#define TIMELIB_WARN_INVALID_TIME 0x102
+#define TIMELIB_WARN_INVALID_DATE 0x103
+#define TIMELIB_WARN_TRAILING_DATA 0x11a
+
+#define TIMELIB_ERR_DOUBLE_TZ 0x201
+#define TIMELIB_ERR_TZID_NOT_FOUND 0x202
+#define TIMELIB_ERR_DOUBLE_TIME 0x203
+#define TIMELIB_ERR_DOUBLE_DATE 0x204
+#define TIMELIB_ERR_UNEXPECTED_CHARACTER 0x205
+#define TIMELIB_ERR_EMPTY_STRING 0x206
+#define TIMELIB_ERR_UNEXPECTED_DATA 0x207
+#define TIMELIB_ERR_NO_TEXTUAL_DAY 0x208
+#define TIMELIB_ERR_NO_TWO_DIGIT_DAY 0x209
+#define TIMELIB_ERR_NO_THREE_DIGIT_DAY_OF_YEAR 0x20a
+#define TIMELIB_ERR_NO_TWO_DIGIT_MONTH 0x20b
+#define TIMELIB_ERR_NO_TEXTUAL_MONTH 0x20c
+#define TIMELIB_ERR_NO_TWO_DIGIT_YEAR 0x20d
+#define TIMELIB_ERR_NO_FOUR_DIGIT_YEAR 0x20e
+#define TIMELIB_ERR_NO_TWO_DIGIT_HOUR 0x20f
+#define TIMELIB_ERR_HOUR_LARGER_THAN_12 0x210
+#define TIMELIB_ERR_MERIDIAN_BEFORE_HOUR 0x211
+#define TIMELIB_ERR_NO_MERIDIAN 0x212
+#define TIMELIB_ERR_NO_TWO_DIGIT_MINUTE 0x213
+#define TIMELIB_ERR_NO_TWO_DIGIT_SECOND 0x214
+#define TIMELIB_ERR_NO_SIX_DIGIT_MICROSECOND 0x215
+#define TIMELIB_ERR_NO_SEP_SYMBOL 0x216
+#define TIMELIB_ERR_EXPECTED_ESCAPE_CHAR 0x217
+#define TIMELIB_ERR_NO_ESCAPED_CHAR 0x218
+#define TIMELIB_ERR_WRONG_FORMAT_SEP 0x219
+#define TIMELIB_ERR_TRAILING_DATA 0x21a
+#define TIMELIB_ERR_DATA_MISSING 0x21b
+
+#define TIMELIB_ZONETYPE_OFFSET 1
+#define TIMELIB_ZONETYPE_ABBR 2
+#define TIMELIB_ZONETYPE_ID 3
+
+typedef struct timelib_error_message {
+ int error_code;
+ int position;
+ char character;
+ char *message;
+} timelib_error_message;
+
+typedef struct timelib_error_container {
+ struct timelib_error_message *error_messages;
+ struct timelib_error_message *warning_messages;
+ int error_count;
+ int warning_count;
+} timelib_error_container;
+
+typedef struct _timelib_tz_lookup_table {
+ char *name;
+ int type;
+ float gmtoffset;
+ char *full_tz_name;
+} timelib_tz_lookup_table;
+
+typedef struct _timelib_tzdb_index_entry {
+ char *id;
+ unsigned int pos;
+} timelib_tzdb_index_entry;
+
+typedef struct _timelib_tzdb {
+ char *version;
+ int index_size;
+ const timelib_tzdb_index_entry *index;
+ const unsigned char *data;
+} timelib_tzdb;
+
#ifndef timelib_malloc
# define timelib_malloc malloc
# define timelib_realloc realloc
@@ -38,8 +310,8 @@
# define timelib_free free
#endif
-#define TIMELIB_VERSION 201605
-#define TIMELIB_ASCII_VERSION "2016.05"
+#define TIMELIB_VERSION 201705
+#define TIMELIB_ASCII_VERSION "2017.05beta7"
#define TIMELIB_NONE 0x00
#define TIMELIB_OVERRIDE_TIME 0x01
@@ -47,51 +319,172 @@
#define TIMELIB_UNSET -99999
-#define TIMELIB_SPECIAL_WEEKDAY 0x01
-#define TIMELIB_SPECIAL_DAY_OF_WEEK_IN_MONTH 0x02
-#define TIMELIB_SPECIAL_LAST_DAY_OF_WEEK_IN_MONTH 0x03
-
-#define TIMELIB_SPECIAL_FIRST_DAY_OF_MONTH 0x01
-#define TIMELIB_SPECIAL_LAST_DAY_OF_MONTH 0x02
-
-#ifndef LONG_MAX
-#define LONG_MAX 2147483647L
-#endif
+/* An entry for each of these error codes is also in the
+ * timelib_error_messages array in timelib.c */
+#define TIMELIB_ERROR_NO_ERROR 0x00
+#define TIMELIB_ERROR_CANNOT_ALLOCATE 0x01
+#define TIMELIB_ERROR_CORRUPT_TRANSITIONS_DONT_INCREASE 0x02
+#define TIMELIB_ERROR_CORRUPT_NO_64BIT_PREAMBLE 0x03
+#define TIMELIB_ERROR_CORRUPT_NO_ABBREVIATION 0x04
+#define TIMELIB_ERROR_UNSUPPORTED_VERSION 0x05
+#define TIMELIB_ERROR_NO_SUCH_TIMEZONE 0x06
-#ifndef LONG_MIN
-#define LONG_MIN (- LONG_MAX - 1)
-#endif
-
-#if defined(_MSC_VER) && !defined(strcasecmp)
-#define strcasecmp stricmp
-#endif
-
-#if defined(_MSC_VER) && !defined(strncasecmp)
-#define strncasecmp strnicmp
+#ifdef __cplusplus
+extern "C" {
#endif
/* Function pointers */
-typedef timelib_tzinfo* (*timelib_tz_get_wrapper)(char *tzname, const timelib_tzdb *tzdb);
+typedef timelib_tzinfo* (*timelib_tz_get_wrapper)(char *tzname, const timelib_tzdb *tzdb, int *error_code);
/* From dow.c */
+/* Calculates the day of the week from y, m, and d. 0=Sunday..6=Saturday */
timelib_sll timelib_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d);
+
+/* Calculates the day of the ISO week from y, m, and d. 1=Monday, 7=Sunday */
timelib_sll timelib_iso_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d);
+
+/* Calculates the day of the year according to y-m-d. 0=Jan 1st..364/365=Dec
+ * 31st */
timelib_sll timelib_day_of_year(timelib_sll y, timelib_sll m, timelib_sll d);
-timelib_sll timelib_daynr_from_weeknr(timelib_sll y, timelib_sll w, timelib_sll d);
+
+/* Calculates the day of the year according to y-w-dow. 0..364/365 */
+timelib_sll timelib_daynr_from_weeknr(timelib_sll iy, timelib_sll iw, timelib_sll id);
+
+/* Calculates the number of days in month m for year y. 28..31 */
timelib_sll timelib_days_in_month(timelib_sll y, timelib_sll m);
+
+/* Calculates the ISO year and week from y, m, and d, into iw and iy */
void timelib_isoweek_from_date(timelib_sll y, timelib_sll m, timelib_sll d, timelib_sll *iw, timelib_sll *iy);
+
+/* Calculates the ISO year, week, and day of week from y, m, and d, into iy,
+ * iw, and id */
+void timelib_isodate_from_date(timelib_sll y, timelib_sll m, timelib_sll d, timelib_sll *iy, timelib_sll *iw, timelib_sll *id);
+
+/* Calculates the year, month, and day from iy, iw, and iw, into y, m, and d */
+void timelib_date_from_isodate(timelib_sll iy, timelib_sll iw, timelib_sll id, timelib_sll *y, timelib_sll *m, timelib_sll *d);
+
+/* Returns true if h, i and s fit in the range 00:00:00..23:59:59, false
+ * otherwise */
int timelib_valid_time(timelib_sll h, timelib_sll i, timelib_sll s);
+
+/* Returns true if m fits in the range 1..12, and d fits in the range
+ * 1..<days-in-month> for year y */
int timelib_valid_date(timelib_sll y, timelib_sll m, timelib_sll d);
/* From parse_date.re */
+
+/* Parses the date/time string in 's' with length 'len' into the constituent
+ * parts of timelib_time*.
+ *
+ * Depending on the contents of the string 's', not all elements might be
+ * filled. You can check whether a specific element has been parsed by
+ * comparing with the TIMELIB_UNSET define.
+ *
+ * If errors occur, this function keeps already parsed elements in the
+ * returned timelib_time* value.
+ *
+ * If the **errors points to a timelib_error_container variable, warnings
+ * and errors will be recorded. You are responsible for freeing the stored
+ * information with timelib_error_container_dtor(). To see whether errors have
+ * occured, inspect errors->errors_count. To see whether warnings have occured,
+ * inspect errors->warnings_count.
+ *
+ * The returned timelib_time* value is dynamically allocated and should be
+ * freed with timelib_time_dtor().
+ */
timelib_time *timelib_strtotime(char *s, size_t len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper);
+
+/* Parses the date/time string in 's' with length 'len' into the constituent
+ * parts of timelib_time* according to the format in 'format'.
+ *
+ * Depending on the contents of the string 's', not all elements might be
+ * filled. You can check whether a specific element has been parsed by
+ * comparing with the TIMELIB_UNSET define.
+ *
+ * If errors occur, this function keeps already parsed elements in the
+ * returned timelib_time* value.
+ *
+ * If the **errors points to a timelib_error_container variable, warnings
+ * and errors will be recorded. You are responsible for freeing the stored
+ * information with timelib_error_container_dtor(). To see whether errors have
+ * occured, inspect errors->errors_count. To see whether warnings have occured,
+ * inspect errors->warnings_count.
+ *
+ * The returned timelib_time* value is dynamically allocated and should be
+ * freed with timelib_time_dtor().
+ */
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);
+
+/* Fills the gaps in the parsed timelib_time with information from the reference date/time in 'now'
+ *
+ * If any of the 'parsed' y, m, d, h, i or s parameters is unset (TIMELIB_UNSET):
+ * - if microtime (us) is unset, then the us of the parsed time is set to 0.
+ * - else if microtime (us) is unset and 'now'->'us' is set, use it, otherwise use 0.
+ *
+ * For either of the 'parsed' y, m, d, h, i, s, z (utc offset in seconds) or
+ * dst is unset, set it to the corresponding value in 'now' if set, otherwise
+ * set it to 0.
+ *
+ * It duplicates tz_abbr if unset in 'parsed' but set in 'now'.
+ *
+ * It duplicates tz_info if unset in 'parsed', but set in 'now' unless
+ * TIMELIB_NO_CLONE is passed, in which case only the pointer in 'parsed' is
+ * set to 'now'.
+ *
+ * If the option TIMELIB_OVERRIDE_TIME is passed and the parsed date/time has
+ * no time portion, the function will ignore the time aspect in 'now' and
+ * instead fill it with zeros.
+ */
void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options);
+
+/* Tries to convert a time zone abbreviation, gmtoffset and/or isdst flag
+ * combination to a time zone identifier.
+ *
+ * If 'abbr' is either 'utc' or 'gmt' (case insensitve) then "UTC" is
+ * returned.
+ *
+ * It first uses the data in the timezonemap.h file to find a matching
+ * abbreviation/GMT offset combination. If not found, it uses the data in
+ * fallbackmap.h to match only the GMT offset/isdst flag to try to find a
+ * match. If nothing is found, NULL is returned.
+ *
+ * The returned char* is not duplicated, and should not be freed.
+ */
char *timelib_timezone_id_from_abbr(const char *abbr, timelib_long gmtoffset, int isdst);
+
+/* Returns an array of known time zone abbreviations
+ *
+ * This file is generated from the time zone database through the
+ * gettzmapping.php scripts, which requires that an up-to-date time zone
+ * database is used with the PHP binary that runs the script.
+ *
+ * Each item in the returned list contains the abbreviation, a flag whether
+ * it's an abbreviation used with DST, the UTC offset in seconds, and the name
+ * of the time zone identifier that this abbreviation belongs to.
+ *
+ * The order for each specific abbreviation is controlled through the
+ * preference list in the gettzmapping.php script. Time zones that match the
+ * pattern ±\d{2,4} are excluded
+ */
const timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void);
-timelib_long timelib_parse_tz_cor(char**);
+
+/**
+ * DEPRECATED, but still used by PHP.
+ */
+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);
/* From parse_iso_intervals.re */
+
+/**
+ * Parses a subset of an ISO 8601 intervals specification string into its
+ * constituent parts.
+ *
+ * If the **errors points to a timelib_error_container variable, warnings
+ * and errors will be recorded. You are responsible for freeing the stored
+ * information with timelib_error_container_dtor(). To see whether errors have
+ * occured, inspect errors->errors_count. To see whether warnings have occured,
+ * inspect errors->warnings_count.
+ */
void timelib_strtointerval(char *s, size_t len,
timelib_time **begin, timelib_time **end,
timelib_rel_time **period, int *recurrences,
@@ -99,67 +492,395 @@ void timelib_strtointerval(char *s, size_t len,
/* From tm2unixtime.c */
+
+/**
+ * Uses the y/m/d/h/i/s fields to calculate and store the equivalent timestamp
+ * in the sse field.
+ *
+ * It uses the time zone information associated with 'time' to account for the
+ * right UTC offset and/or DST rules. You can associate time zone information
+ * with the timelib_set_timezone_* functions (see below).
+ *
+ * If the type is 'TIMELIB_ZONETYPE_ID' and there is no associated tzinfo, it
+ * will use the second argument 'tzi' to provide the rules necessary to
+ * calculate the right timestamp.
+ */
void timelib_update_ts(timelib_time* time, timelib_tzinfo* tzi);
+
+/**
+ * Takes the information from the y/m/d/h/i/s fields and makes sure their
+ * values are in the right range.
+ *
+ * If a value under- or overflows it will adjust the larger measure up (or
+ * down). It also takes into account leap days.
+ */
void timelib_do_normalize(timelib_time *base);
+
+/**
+ * Takes the information from the y/m/d/h/i/s fields of 'rt' and makes sure
+ * their values are in the right range.
+ *
+ * If a value under- or overflows it will adjust the larger measure up (or
+ * down). As this function operates on a *relative date/time*, it also takes
+ * into account leap days and correctly accounts for the difference depending
+ * on the base date/time in 'base'.
+ */
void timelib_do_rel_normalize(timelib_time *base, timelib_rel_time *rt);
/* From unixtime2tm.c */
-int timelib_apply_localtime(timelib_time *t, unsigned int localtime);
+
+/**
+ * Takes the unix timestamp in seconds from 'ts' and populates the y/m/d/h/i/s
+ * fields of 'tm' without taking time zones into account
+ */
void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts);
+
+/**
+ * Takes the Unix timestamp from 'ts', and calculates the y/m/d/h/i/s fields
+ * according to the time zone information attached to 'tm'.
+ */
void timelib_unixtime2local(timelib_time *tm, timelib_sll ts);
+
+/**
+ * Takes the Unix timestamp stored in 'tm', and calculates the y/m/d/h/i/s
+ * fields according to the time zone information attached to 'tm'.
+ */
void timelib_update_from_sse(timelib_time *tm);
+
+/**
+ * Attaches the UTC offset as time zone information to 't'.
+ *
+ * 'utc_offset' is in seconds East of UTC.
+ */
void timelib_set_timezone_from_offset(timelib_time *t, timelib_sll utc_offset);
+
+/**
+ * Attaches the information from 'abbr_info' as time zone information to 't'.
+ *
+ * The timelib_abbr_info struct contains an abbreviation ('abbr') which string
+ * value is duplicated, as well as a 'utc_offset' and 'dst' flag. It only
+ * supports a 'dst' change over of 1 hour.
+ */
void timelib_set_timezone_from_abbr(timelib_time *t, timelib_abbr_info abbr_info);
+
+/**
+ * Attaches the time zone information in 'tz' to to 't'.
+ *
+ * It fetches the right UTC offset that is currently stored in the time
+ * stamp field in 't' ('sse'), and assigns that to the 'z' field and 'dst'
+ * field (whether DST is in effect at the time). It also sets the current
+ * abbrevation to the 'tz_addr' field, making sure that if a value was already
+ * set it was freed.
+ *
+ * The time zone information in 'tz' is *not* duplicated into the 't' field so
+ * it should not be freed until all timelib_time* variables have been freed as
+ * well.
+ */
void timelib_set_timezone(timelib_time *t, timelib_tzinfo *tz);
/* From parse_tz.c */
+
+/**
+ * Returns whether the time zone ID 'timezone' is available in the time zone
+ * database as pointed to be 'tzdb'.
+ */
int timelib_timezone_id_is_valid(char *timezone, const timelib_tzdb *tzdb);
-timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb);
+
+/**
+ * Converts the binary stored time zone information from 'tzdb' for the time
+ * zone 'timeozne' into a structure the library can use for calculations.
+ *
+ * The function can be used on both timelib_builtin_db as well as a time zone
+ * db as opened by timelib_zoneinfo.
+ * The function will return null upon failure, and also set an error code
+ * through 'error_code'. 'error_code' must not be a null pointer. The error
+ * code is one of the TIMELIB_ERROR_* constants as listed above. These error
+ * constants can be converted into a string by timelib_get_error_message.
+ *
+ * This function allocates memory for the new time zone structure, which must
+ * be freed after use. Although it is recommended that a cache of each used
+ * time zone is kept.
+ */
+timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb, int *error_code);
+
+/**
+ * Frees up the resources allocated by 'timelib_parse_tzfile'.
+ */
+void timelib_tzinfo_dtor(timelib_tzinfo *tz);
+
+/**
+ * Deep-clones a timelib_tzinfo structure.
+ *
+ * This allocates resources that need to be freed with 'timelib_tzinfo_dtor'
+ */
+timelib_tzinfo* timelib_tzinfo_clone(timelib_tzinfo *tz);
+
+/**
+ * Returns whether DST is active with time zone 'tz' for the time stamp 'ts'.
+ *
+ * Returns 0 if DST is not active, 1 if DST is active, or -1 if no transitions
+ * were available through 'tz'.
+ */
int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz);
+
+/**
+ * Returns offset information with time zone 'tz' for the time stamp 'ts'.
+ *
+ * The returned information contains: the offset in seconds East of UTC (in
+ * 'offset'), whether DST is active ('is_dst'), what the current time zone
+ * abbreviation is ('abbr') and the transition time that got to this state (in
+ * 'transistion_time');
+ */
timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz);
+
+/**
+ * Returns the UTC offset currently applicable for the information stored in 't'.
+ *
+ * The value returned is the UTC offset in seconds East.
+ */
timelib_sll timelib_get_current_offset(timelib_time *t);
+
+/**
+ * Displays debugging information about the time zone information in 'tz'.
+ */
void timelib_dump_tzinfo(timelib_tzinfo *tz);
+
+/**
+ * Returns a pointer to the built-in time zone database.
+ *
+ * You must *not* free the returned pointer as it is part of the text segment.
+ */
const timelib_tzdb *timelib_builtin_db(void);
-const timelib_tzdb_index_entry *timelib_timezone_builtin_identifiers_list(int *count);
-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);
+
+/**
+ * Returns a pointer to the start of an array containing a list of timezone identifiers.
+ *
+ * The amount of entries in the array is returned through the 'count' OUT parameter.
+ *
+ * Each entry contains the time zone ID ('id' field), and the position within the time zone
+ * information ('pos' field). The pos field should not be used.
+ */
+const timelib_tzdb_index_entry *timelib_timezone_identifiers_list(timelib_tzdb *tzdb, int *count);
+
+/* From parse_zoneinfo.c */
+
+/**
+ * Scans the directory and subdirectories of 'directory' for valid time zone files and builds
+ * a time zone database out of these files.
+ *
+ * Typically, the directory should point to '/usr/share/zoneinfo'.
+ *
+ * Unlike 'timelib_builtin_db', the return value of this function must be freed
+ * with the 'timelib_zoneinfo_dtor' function.
+ */
+timelib_tzdb *timelib_zoneinfo(char *directory);
+
+/**
+ * Frees up the resources as created through 'timelib_zoneinfo'.
+ *
+ * This function must be used to free up all the resources that have been
+ * allocated while calling 'timelib_zoneinfo'.
+ */
+void timelib_zoneinfo_dtor(timelib_tzdb *tzdb);
/* From timelib.c */
-timelib_tzinfo* timelib_tzinfo_ctor(char *name);
-void timelib_time_tz_abbr_update(timelib_time* tm, char* tz_abbr);
-void timelib_time_tz_name_update(timelib_time* tm, char* tz_name);
-void timelib_tzinfo_dtor(timelib_tzinfo *tz);
-timelib_tzinfo* timelib_tzinfo_clone(timelib_tzinfo *tz);
+/**
+ * Returns a static string containing an error message belonging to a specific
+ * error code.
+ */
+const char *timelib_get_error_message(int error_code);
+
+/**
+ * Allocates resources for the relative time structure.
+ *
+ * Must be freed with 'timelib_rel_time_dtor'.
+ */
timelib_rel_time* timelib_rel_time_ctor(void);
+
+/**
+ * Frees up the resources as allocated through 'timelib_rel_time_ctor'.
+ */
void timelib_rel_time_dtor(timelib_rel_time* t);
+
+/**
+ * Creates a new timelib_rel_time resource and copies over the information
+ * from 'tz'.
+ *
+ * Must be freed with 'timelib_rel_time_dtor'.
+ */
timelib_rel_time* timelib_rel_time_clone(timelib_rel_time *tz);
+/**
+ * Allocates resources for the time structure.
+ *
+ * Must be freed with 'timelib_time_dtor'.
+ */
timelib_time* timelib_time_ctor(void);
-void timelib_time_set_option(timelib_time* tm, int option, void* option_value);
+
+/**
+ * Frees up the resources as allocated through 'timelib_time_ctor'.
+ */
void timelib_time_dtor(timelib_time* t);
+
+/**
+ * Creates a new timelib_time resource and copies over the information
+ * from 'orig'.
+ *
+ * Must be freed with 'timelib_time_dtor'.
+ */
timelib_time* timelib_time_clone(timelib_time* orig);
+
+/**
+ * Compares two timelib_time structures and returns which one is earlier in
+ * time.
+ *
+ * To decide which comes earlier it uses the 'sse' (Seconds Since Epoch) and
+ * 'us' (microseconds) fields.
+ *
+ * Returns -1 if t1 < t2, 0 if t1 == t2, and -1 if t1 > t2.
+ */
int timelib_time_compare(timelib_time *t1, timelib_time *t2);
-void timelib_set_fraction_from_timeval(timelib_time *t, struct timeval tp);
+/**
+ * Allocates resources for the time offset structure.
+ *
+ * Must be freed with 'timelib_time_offset_dtor'.
+ */
timelib_time_offset* timelib_time_offset_ctor(void);
+
+/**
+ * Frees up the resources as allocated through 'timelib_time_offset_ctor'.
+ */
void timelib_time_offset_dtor(timelib_time_offset* t);
+/**
+ * Frees up the resources allocated while converting strings to timelib_time
+ * structures with the timelib_strtotime and timelib_strtointerval functions.
+ */
void timelib_error_container_dtor(timelib_error_container *errors);
+/**
+ * Converts the 'sse' value of 'd' to a timelib_long type.
+ *
+ * If the value fits in the TIMELIB_LONG_MIN and TIMELIB_LONG_MAX range, the
+ * value is cast to (timelib_long) and returned. If *error is not a NULL
+ * pointer, it will be set to 0.
+ *
+ * If the value does *not* fit in the range, the function returns 0 and if
+ * *error is not a NULL pointer, it will be set to 1.
+ *
+ * timelib_long is a 32 bit signed long integer on 32 bit platforms, and a 64
+ * bit signed long long integer on 64 bit platforms. In other words, it makes
+ * sure that the value in 'sse' (which is always a signed long long 64 bit
+ * integer) can be used safely outside of the library.
+ */
timelib_long timelib_date_to_int(timelib_time *d, int *error);
+
+/**
+ * Displays debugging information about the date/time information stored in 'd'.
+ *
+ * 'options' is a bit field, where:
+ * - 1 controls whether the relative time portion is shown.
+ * - 2 controls whether the zone type is shown.
+ */
void timelib_dump_date(timelib_time *d, int options);
+
+/**
+ * Displays debugging information about the relative time information stored
+ * in 'd'.
+ */
void timelib_dump_rel_time(timelib_rel_time *d);
+/**
+ * Converts a decimal hour into hour/min/sec components
+ */
void timelib_decimal_hour_to_hms(double h, int *hour, int *min, int *sec);
-timelib_long timelib_parse_tz_cor(char **ptr);
+
+/**
+ * Converts hour/min/sec values into a decimal hour
+ */
+void timelib_hms_to_decimal_hour(int hour, int min, int sec, double *h);
/* from astro.c */
-double timelib_ts_to_juliandate(timelib_sll ts);
+
+/**
+ * Converts the Unix Epoch time stamp 'ts' to a Julian Day
+ *
+ * The value returned is the number of whole days since -4714-11-24T12:00:00 UTC
+ * (in the proleptic Gregorian calendar):
+ * https://en.wikipedia.org/wiki/Julian_day
+ */
+double timelib_ts_to_julianday(timelib_sll ts);
+
+/**
+ * Converts the Unix Epoch time stamp 'ts' to the J2000 epoch
+ *
+ * The value returned is the number of whole days since 2000-01-01T12:00:00
+ * UTC: https://en.wikipedia.org/wiki/Epoch_(astronomy)#Julian_years_and_J2000
+ */
+double timelib_ts_to_j2000(timelib_sll ts);
+
+/**
+ * Calculates when the Sun is above a certain latitude.
+ *
+ * Parameters:
+ * - time: A timelib_time time describing that needs to specific midnight for a
+ * specific day.
+ * - lon: The longitude of the observer (East positive, West negative).
+ * - lat: The latitude of the observer (North positive, South negative).
+ * - altit: The altitude. Set to -35/60 for rise/set, -6 for civil twilight,
+ * -12 for nautical, and -18 for astronomical twilight.
+ * - upper_limb: set to non-zero for rise/set calculations, and 0 for twilight
+ * calculations.
+ *
+ * Out Parameters:
+ * - h_rise: The decimal hour when the Sun rises
+ * - h_set: The decimal hour when the Sun sets
+ * - ts_rise: The Unix timestamp of the Sun rising
+ * - ts_set: The Unix timestamp of the Sun setting
+ * - ts_transit: The Unix timestmap of the Sun transitting through South
+ *
+ * Return Values:
+ * - 0: The Sun rises and sets.
+ * - +1: The Sun is always above the horizon. (ts_rise is set to ts_transit -
+ * (12 * 3600); ts_set is set to ts_transit + (12 * 3600).
+ * - -1: The Sun is awlays below the horizon. (ts_rise and ts_set are set
+ * to ts_transit)
+ */
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);
/* from interval.c */
+
+/**
+ * Calculates the difference between two times
+ *
+ * The result is a timelib_rel_time structure that describes how you can
+ * convert from 'one' to 'two' with 'timelib_add'. This does *not* necessarily
+ * mean that you can go from 'two' to 'one' by using 'timelib_sub' due to the
+ * way months and days are calculated.
+ */
timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two);
+
+/**
+ * Adds the relative time information 'interval' to the base time 't'.
+ *
+ * This can be a relative time as created by 'timelib_diff', but also by more
+ * complex statements such as "next workday".
+ */
timelib_time *timelib_add(timelib_time *t, timelib_rel_time *interval);
+
+/**
+ * Subtracts the relative time information 'interval' to the base time 't'.
+ *
+ * This can be a relative time as created by 'timelib_diff'. Unlike with
+ * 'timelib_add', this does not support more complex statements such as "next
+ * workday".
+ */
timelib_time *timelib_sub(timelib_time *t, timelib_rel_time *interval);
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
#endif