mirror of
https://github.com/php/php-src.git
synced 2024-09-22 10:27:25 +00:00
Fixed bug #75577: DateTime::createFromFormat does not accept 'v' format specifier, by updating timelib to 2018.01alpha2
This commit is contained in:
parent
44d2c8c6dd
commit
43f7a5735c
File diff suppressed because it is too large
Load Diff
@ -141,9 +141,9 @@ typedef struct _Scanner {
|
||||
} Scanner;
|
||||
|
||||
typedef struct _timelib_lookup_table {
|
||||
const char *name;
|
||||
int type;
|
||||
int value;
|
||||
const char *name;
|
||||
int type;
|
||||
int value;
|
||||
} timelib_lookup_table;
|
||||
|
||||
typedef struct _timelib_relunit {
|
||||
@ -619,7 +619,7 @@ static const timelib_relunit* timelib_lookup_relunit(char **ptr)
|
||||
const timelib_relunit *tp, *value = NULL;
|
||||
|
||||
while (**ptr != '\0' && **ptr != ' ' && **ptr != ',' && **ptr != '\t' && **ptr != ';' && **ptr != ':' &&
|
||||
**ptr != '/' && **ptr != '.' && **ptr != '-' && **ptr != '(' && **ptr != ')' ) {
|
||||
**ptr != '/' && **ptr != '.' && **ptr != '-' && **ptr != '(' && **ptr != ')' ) {
|
||||
++*ptr;
|
||||
}
|
||||
end = *ptr;
|
||||
@ -771,6 +771,37 @@ static timelib_long timelib_parse_tz_cor(char **ptr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static timelib_long timelib_parse_tz_minutes(char **ptr, timelib_time *t)
|
||||
{
|
||||
timelib_long retval = TIMELIB_UNSET;
|
||||
char *begin = *ptr;
|
||||
|
||||
/* First character must be +/- */
|
||||
if (**ptr != '+' && **ptr != '-') {
|
||||
return retval;
|
||||
}
|
||||
|
||||
++*ptr;
|
||||
while (isdigit(**ptr)) {
|
||||
++*ptr;
|
||||
}
|
||||
|
||||
if (*begin == '+') {
|
||||
t->is_localtime = 1;
|
||||
t->zone_type = TIMELIB_ZONETYPE_OFFSET;
|
||||
t->dst = 0;
|
||||
|
||||
retval = sMIN(strtol(begin + 1, NULL, 10));
|
||||
} else if (*begin == '-') {
|
||||
t->is_localtime = 1;
|
||||
t->zone_type = TIMELIB_ZONETYPE_OFFSET;
|
||||
t->dst = 0;
|
||||
|
||||
retval = -1 * sMIN(strtol(begin + 1, NULL, 10));
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
timelib_tzinfo *res;
|
||||
@ -1906,15 +1937,90 @@ static void timelib_time_reset_unset_fields(timelib_time *time)
|
||||
if (time->us == TIMELIB_UNSET ) time->us = 0;
|
||||
}
|
||||
|
||||
static const timelib_format_specifier default_format_map[] = {
|
||||
{'+', TIMELIB_FORMAT_ALLOW_EXTRA_CHARACTERS},
|
||||
{'#', TIMELIB_FORMAT_ANY_SEPARATOR},
|
||||
{'j', TIMELIB_FORMAT_DAY_TWO_DIGIT},
|
||||
{'d', TIMELIB_FORMAT_DAY_TWO_DIGIT_PADDED},
|
||||
{'z', TIMELIB_FORMAT_DAY_OF_YEAR},
|
||||
{'S', TIMELIB_FORMAT_DAY_SUFFIX},
|
||||
{'U', TIMELIB_FORMAT_EPOCH_SECONDS},
|
||||
{'\\', TIMELIB_FORMAT_ESCAPE},
|
||||
{'h', TIMELIB_FORMAT_HOUR_TWO_DIGIT_12_MAX},
|
||||
{'g', TIMELIB_FORMAT_HOUR_TWO_DIGIT_12_MAX_PADDED},
|
||||
{'H', TIMELIB_FORMAT_HOUR_TWO_DIGIT_24_MAX},
|
||||
{'G', TIMELIB_FORMAT_HOUR_TWO_DIGIT_24_MAX_PADDED},
|
||||
{'a', TIMELIB_FORMAT_MERIDIAN},
|
||||
{'A', TIMELIB_FORMAT_MERIDIAN},
|
||||
{'u', TIMELIB_FORMAT_MICROSECOND_SIX_DIGIT},
|
||||
{'v', TIMELIB_FORMAT_MILLISECOND_THREE_DIGIT},
|
||||
{'i', TIMELIB_FORMAT_MINUTE_TWO_DIGIT},
|
||||
{'n', TIMELIB_FORMAT_MONTH_TWO_DIGIT},
|
||||
{'m', TIMELIB_FORMAT_MONTH_TWO_DIGIT_PADDED},
|
||||
{'?', TIMELIB_FORMAT_RANDOM_CHAR},
|
||||
{'!', TIMELIB_FORMAT_RESET_ALL},
|
||||
{'|', TIMELIB_FORMAT_RESET_ALL_WHEN_NOT_SET},
|
||||
{'s', TIMELIB_FORMAT_SECOND_TWO_DIGIT},
|
||||
{';', TIMELIB_FORMAT_SEPARATOR},
|
||||
{':', TIMELIB_FORMAT_SEPARATOR},
|
||||
{'/', TIMELIB_FORMAT_SEPARATOR},
|
||||
{'.', TIMELIB_FORMAT_SEPARATOR},
|
||||
{',', TIMELIB_FORMAT_SEPARATOR},
|
||||
{'-', TIMELIB_FORMAT_SEPARATOR},
|
||||
{'(', TIMELIB_FORMAT_SEPARATOR},
|
||||
{')', TIMELIB_FORMAT_SEPARATOR},
|
||||
{'*', TIMELIB_FORMAT_SKIP_TO_SEPARATOR},
|
||||
{'D', TIMELIB_FORMAT_TEXTUAL_DAY_3_LETTER},
|
||||
{'l', TIMELIB_FORMAT_TEXTUAL_DAY_FULL},
|
||||
{'M', TIMELIB_FORMAT_TEXTUAL_MONTH_3_LETTER},
|
||||
{'F', TIMELIB_FORMAT_TEXTUAL_MONTH_FULL},
|
||||
{'e', TIMELIB_FORMAT_TIMEZONE_OFFSET},
|
||||
{'P', TIMELIB_FORMAT_TIMEZONE_OFFSET},
|
||||
{'T', TIMELIB_FORMAT_TIMEZONE_OFFSET},
|
||||
{'O', TIMELIB_FORMAT_TIMEZONE_OFFSET},
|
||||
{' ', TIMELIB_FORMAT_WHITESPACE},
|
||||
{'y', TIMELIB_FORMAT_YEAR_TWO_DIGIT},
|
||||
{'Y', TIMELIB_FORMAT_YEAR_FOUR_DIGIT},
|
||||
{'\0', TIMELIB_FORMAT_END}
|
||||
};
|
||||
|
||||
static const timelib_format_config default_format_config = {
|
||||
default_format_map,
|
||||
// No prefix required by default.
|
||||
'\0'
|
||||
};
|
||||
|
||||
static timelib_format_specifier_code timelib_lookup_format(char input, const timelib_format_specifier* format_map)
|
||||
{
|
||||
while (format_map && format_map->specifier != '\0') {
|
||||
if (format_map->specifier == input) {
|
||||
return format_map->code;
|
||||
}
|
||||
format_map++;
|
||||
}
|
||||
return TIMELIB_FORMAT_LITERAL;
|
||||
}
|
||||
|
||||
timelib_time *timelib_parse_from_format(char *format, char *string, size_t len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper)
|
||||
{
|
||||
char *fptr = format;
|
||||
char *ptr = string;
|
||||
char *begin;
|
||||
timelib_sll tmp;
|
||||
Scanner in;
|
||||
Scanner *s = ∈
|
||||
int allow_extra = 0;
|
||||
return timelib_parse_from_format_with_map(format, string, len, errors, tzdb, tz_get_wrapper, &default_format_config);
|
||||
}
|
||||
|
||||
timelib_time *timelib_parse_from_format_with_map(char *format, char *string, size_t len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper, const timelib_format_config* format_config)
|
||||
{
|
||||
char *fptr = format;
|
||||
char *ptr = string;
|
||||
char *begin;
|
||||
timelib_sll tmp;
|
||||
Scanner in;
|
||||
Scanner *s = ∈
|
||||
bool allow_extra = false;
|
||||
bool prefix_found = false;
|
||||
int iso_year = TIMELIB_UNSET;
|
||||
int iso_week_of_year = TIMELIB_UNSET;
|
||||
int iso_day_of_week = TIMELIB_UNSET;
|
||||
char prefix_char = format_config->prefix_char;
|
||||
const timelib_format_specifier *format_map = format_config->format_map;
|
||||
|
||||
memset(&in, 0, sizeof(in));
|
||||
in.errors = timelib_malloc(sizeof(timelib_error_container));
|
||||
@ -1940,9 +2046,41 @@ timelib_time *timelib_parse_from_format(char *format, char *string, size_t len,
|
||||
/* Loop over the format string */
|
||||
while (*fptr && *ptr) {
|
||||
begin = ptr;
|
||||
switch (*fptr) {
|
||||
case 'D': /* three letter day */
|
||||
case 'l': /* full day */
|
||||
|
||||
if (prefix_char) {
|
||||
/* There are 2 cases where the input string and format string
|
||||
* should match the next literal:
|
||||
*
|
||||
* 1. No prefix has been specified yet in the format, so expect 1:1
|
||||
* match.
|
||||
* 2. Sequential prefix characters indicating that the second
|
||||
* prefix is escaped. (e.g. "%%" is expecting literal "%")
|
||||
*/
|
||||
if ((!prefix_found && *fptr != prefix_char) ||
|
||||
(prefix_found && *fptr == prefix_char)) {
|
||||
if (*fptr != *ptr) {
|
||||
add_pbf_error(s, TIMELIB_ERR_FORMAT_LITERAL_MISMATCH, "Format literal not found", string, begin);
|
||||
}
|
||||
ptr++;
|
||||
fptr++;
|
||||
prefix_found = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*fptr == prefix_char) {
|
||||
fptr++;
|
||||
prefix_found = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Fall through case is that the prefix has been found and the next
|
||||
* character is the format specifier. */
|
||||
prefix_found = false;
|
||||
}
|
||||
|
||||
switch (timelib_lookup_format(*fptr, format_map)) {
|
||||
case TIMELIB_FORMAT_TEXTUAL_DAY_3_LETTER: /* three letter day */
|
||||
case TIMELIB_FORMAT_TEXTUAL_DAY_FULL: /* full day */
|
||||
{
|
||||
const timelib_relunit* tmprel = 0;
|
||||
|
||||
@ -1958,17 +2096,17 @@ timelib_time *timelib_parse_from_format(char *format, char *string, size_t len,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'd': /* two digit day, with leading zero */
|
||||
case 'j': /* two digit day, without leading zero */
|
||||
case TIMELIB_FORMAT_DAY_TWO_DIGIT: /* two digit day, without leading zero */
|
||||
case TIMELIB_FORMAT_DAY_TWO_DIGIT_PADDED: /* two digit day, with leading zero */
|
||||
TIMELIB_CHECK_NUMBER;
|
||||
if ((s->time->d = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
|
||||
add_pbf_error(s, TIMELIB_ERR_NO_TWO_DIGIT_DAY, "A two digit day could not be found", string, begin);
|
||||
}
|
||||
break;
|
||||
case 'S': /* day suffix, ignored, nor checked */
|
||||
case TIMELIB_FORMAT_DAY_SUFFIX: /* day suffix, ignored, nor checked */
|
||||
timelib_skip_day_suffix((char **) &ptr);
|
||||
break;
|
||||
case 'z': /* day of year - resets month (0 based) - also initializes everything else to !TIMELIB_UNSET */
|
||||
case TIMELIB_FORMAT_DAY_OF_YEAR: /* day of year - resets month (0 based) - also initializes everything else to !TIMELIB_UNSET */
|
||||
TIMELIB_CHECK_NUMBER;
|
||||
if ((tmp = timelib_get_nr((char **) &ptr, 3)) == TIMELIB_UNSET) {
|
||||
add_pbf_error(s, TIMELIB_ERR_NO_THREE_DIGIT_DAY_OF_YEAR, "A three digit day-of-year could not be found", string, begin);
|
||||
@ -1979,15 +2117,15 @@ timelib_time *timelib_parse_from_format(char *format, char *string, size_t len,
|
||||
}
|
||||
break;
|
||||
|
||||
case 'm': /* two digit month, with leading zero */
|
||||
case 'n': /* two digit month, without leading zero */
|
||||
case TIMELIB_FORMAT_MONTH_TWO_DIGIT: /* two digit month, without leading zero */
|
||||
case TIMELIB_FORMAT_MONTH_TWO_DIGIT_PADDED: /* two digit month, with leading zero */
|
||||
TIMELIB_CHECK_NUMBER;
|
||||
if ((s->time->m = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
|
||||
add_pbf_error(s, TIMELIB_ERR_NO_TWO_DIGIT_MONTH, "A two digit month could not be found", string, begin);
|
||||
}
|
||||
break;
|
||||
case 'M': /* three letter month */
|
||||
case 'F': /* full month */
|
||||
case TIMELIB_FORMAT_TEXTUAL_MONTH_3_LETTER: /* three letter month */
|
||||
case TIMELIB_FORMAT_TEXTUAL_MONTH_FULL: /* full month */
|
||||
tmp = timelib_lookup_month((char **) &ptr);
|
||||
if (!tmp) {
|
||||
add_pbf_error(s, TIMELIB_ERR_NO_TEXTUAL_MONTH, "A textual month could not be found", string, begin);
|
||||
@ -1995,7 +2133,7 @@ timelib_time *timelib_parse_from_format(char *format, char *string, size_t len,
|
||||
s->time->m = tmp;
|
||||
}
|
||||
break;
|
||||
case 'y': /* two digit year */
|
||||
case TIMELIB_FORMAT_YEAR_TWO_DIGIT: /* two digit year */
|
||||
{
|
||||
int length = 0;
|
||||
TIMELIB_CHECK_NUMBER;
|
||||
@ -2005,14 +2143,14 @@ timelib_time *timelib_parse_from_format(char *format, char *string, size_t len,
|
||||
TIMELIB_PROCESS_YEAR(s->time->y, length);
|
||||
}
|
||||
break;
|
||||
case 'Y': /* four digit year */
|
||||
case TIMELIB_FORMAT_YEAR_FOUR_DIGIT: /* four digit year */
|
||||
TIMELIB_CHECK_NUMBER;
|
||||
if ((s->time->y = timelib_get_nr((char **) &ptr, 4)) == TIMELIB_UNSET) {
|
||||
add_pbf_error(s, TIMELIB_ERR_NO_FOUR_DIGIT_YEAR, "A four digit year could not be found", string, begin);
|
||||
}
|
||||
break;
|
||||
case 'g': /* two digit hour, with leading zero */
|
||||
case 'h': /* two digit hour, without leading zero */
|
||||
case TIMELIB_FORMAT_HOUR_TWO_DIGIT_12_MAX: /* two digit hour, without leading zero */
|
||||
case TIMELIB_FORMAT_HOUR_TWO_DIGIT_12_MAX_PADDED: /* two digit hour, with leading zero */
|
||||
TIMELIB_CHECK_NUMBER;
|
||||
if ((s->time->h = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
|
||||
add_pbf_error(s, TIMELIB_ERR_NO_TWO_DIGIT_HOUR, "A two digit hour could not be found", string, begin);
|
||||
@ -2021,15 +2159,14 @@ timelib_time *timelib_parse_from_format(char *format, char *string, size_t len,
|
||||
add_pbf_error(s, TIMELIB_ERR_HOUR_LARGER_THAN_12, "Hour can not be higher than 12", string, begin);
|
||||
}
|
||||
break;
|
||||
case 'G': /* two digit hour, with leading zero */
|
||||
case 'H': /* two digit hour, without leading zero */
|
||||
case TIMELIB_FORMAT_HOUR_TWO_DIGIT_24_MAX_PADDED: /* two digit hour, with leading zero */
|
||||
case TIMELIB_FORMAT_HOUR_TWO_DIGIT_24_MAX: /* two digit hour, without leading zero */
|
||||
TIMELIB_CHECK_NUMBER;
|
||||
if ((s->time->h = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
|
||||
add_pbf_error(s, TIMELIB_ERR_NO_TWO_DIGIT_HOUR, "A two digit hour could not be found", string, begin);
|
||||
}
|
||||
break;
|
||||
case 'a': /* am/pm/a.m./p.m. */
|
||||
case 'A': /* AM/PM/A.M./P.M. */
|
||||
case TIMELIB_FORMAT_MERIDIAN: /* am/pm/a.m./p.m. AM/PM/A.M./P.M. */
|
||||
if (s->time->h == TIMELIB_UNSET) {
|
||||
add_pbf_error(s, TIMELIB_ERR_MERIDIAN_BEFORE_HOUR, "Meridian can only come after an hour has been found", string, begin);
|
||||
} else if ((tmp = timelib_meridian_with_check((char **) &ptr, s->time->h)) == TIMELIB_UNSET) {
|
||||
@ -2038,7 +2175,7 @@ timelib_time *timelib_parse_from_format(char *format, char *string, size_t len,
|
||||
s->time->h += tmp;
|
||||
}
|
||||
break;
|
||||
case 'i': /* two digit minute, with leading zero */
|
||||
case TIMELIB_FORMAT_MINUTE_TWO_DIGIT: /* two digit minute, with leading zero */
|
||||
{
|
||||
int length;
|
||||
timelib_sll min;
|
||||
@ -2052,7 +2189,7 @@ timelib_time *timelib_parse_from_format(char *format, char *string, size_t len,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 's': /* two digit second, with leading zero */
|
||||
case TIMELIB_FORMAT_SECOND_TWO_DIGIT: /* two digit second, with leading zero */
|
||||
{
|
||||
int length;
|
||||
timelib_sll sec;
|
||||
@ -2066,7 +2203,7 @@ timelib_time *timelib_parse_from_format(char *format, char *string, size_t len,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'u': /* up to six digit microsecond */
|
||||
case TIMELIB_FORMAT_MICROSECOND_SIX_DIGIT: /* up to six digit microsecond */
|
||||
{
|
||||
double f;
|
||||
char *tptr;
|
||||
@ -2080,10 +2217,24 @@ timelib_time *timelib_parse_from_format(char *format, char *string, size_t len,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ' ': /* any sort of whitespace (' ' and \t) */
|
||||
case TIMELIB_FORMAT_MILLISECOND_THREE_DIGIT: /* up to three digit millisecond */
|
||||
{
|
||||
double f;
|
||||
char *tptr;
|
||||
|
||||
TIMELIB_CHECK_NUMBER;
|
||||
tptr = ptr;
|
||||
if ((f = timelib_get_nr((char **) &ptr, 3)) == TIMELIB_UNSET || (ptr - tptr < 1)) {
|
||||
add_pbf_error(s, TIMELIB_ERR_NO_THREE_DIGIT_MILLISECOND, "A three digit millisecond could not be found", string, begin);
|
||||
} else {
|
||||
s->time->us = (f * pow(10, 3 - (ptr - tptr)) * 1000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TIMELIB_FORMAT_WHITESPACE: /* any sort of whitespace (' ' and \t) */
|
||||
timelib_eat_spaces((char **) &ptr);
|
||||
break;
|
||||
case 'U': /* epoch seconds */
|
||||
case TIMELIB_FORMAT_EPOCH_SECONDS: /* epoch seconds */
|
||||
TIMELIB_CHECK_SIGNED_NUMBER;
|
||||
TIMELIB_HAVE_RELATIVE();
|
||||
tmp = timelib_get_unsigned_nr((char **) &ptr, 24);
|
||||
@ -2097,36 +2248,15 @@ timelib_time *timelib_parse_from_format(char *format, char *string, size_t len,
|
||||
s->time->z = 0;
|
||||
s->time->dst = 0;
|
||||
break;
|
||||
|
||||
case 'e': /* timezone */
|
||||
case 'P': /* timezone */
|
||||
case 'T': /* timezone */
|
||||
case 'O': /* timezone */
|
||||
{
|
||||
int tz_not_found;
|
||||
s->time->z = timelib_parse_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
|
||||
if (tz_not_found) {
|
||||
add_pbf_error(s, TIMELIB_ERR_TZID_NOT_FOUND, "The timezone could not be found in the database", string, begin);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '#': /* separation symbol */
|
||||
if (*ptr == ';' || *ptr == ':' || *ptr == '/' || *ptr == '.' || *ptr == ',' || *ptr == '-' || *ptr == '(' || *ptr == ')') {
|
||||
case TIMELIB_FORMAT_ANY_SEPARATOR: /* separation symbol */
|
||||
if (timelib_lookup_format(*ptr, format_map) == TIMELIB_FORMAT_SEPARATOR) {
|
||||
++ptr;
|
||||
} else {
|
||||
add_pbf_error(s, TIMELIB_ERR_NO_SEP_SYMBOL, "The separation symbol ([;:/.,-]) could not be found", string, begin);
|
||||
}
|
||||
break;
|
||||
|
||||
case ';':
|
||||
case ':':
|
||||
case '/':
|
||||
case '.':
|
||||
case ',':
|
||||
case '-':
|
||||
case '(':
|
||||
case ')':
|
||||
case TIMELIB_FORMAT_SEPARATOR:
|
||||
if (*ptr == *fptr) {
|
||||
++ptr;
|
||||
} else {
|
||||
@ -2134,19 +2264,19 @@ timelib_time *timelib_parse_from_format(char *format, char *string, size_t len,
|
||||
}
|
||||
break;
|
||||
|
||||
case '!': /* reset all fields to default */
|
||||
case TIMELIB_FORMAT_RESET_ALL: /* reset all fields to default */
|
||||
timelib_time_reset_fields(s->time);
|
||||
break; /* break intentionally not missing */
|
||||
|
||||
case '|': /* reset all fields to default when not set */
|
||||
case TIMELIB_FORMAT_RESET_ALL_WHEN_NOT_SET: /* reset all fields to default when not set */
|
||||
timelib_time_reset_unset_fields(s->time);
|
||||
break; /* break intentionally not missing */
|
||||
|
||||
case '?': /* random char */
|
||||
case TIMELIB_FORMAT_RANDOM_CHAR: /* random char */
|
||||
++ptr;
|
||||
break;
|
||||
|
||||
case '\\': /* escaped char */
|
||||
case TIMELIB_FORMAT_ESCAPE: /* escaped char */
|
||||
if(!fptr[1]) {
|
||||
add_pbf_error(s, TIMELIB_ERR_EXPECTED_ESCAPE_CHAR, "Escaped character expected", string, begin);
|
||||
break;
|
||||
@ -2159,14 +2289,52 @@ timelib_time *timelib_parse_from_format(char *format, char *string, size_t len,
|
||||
}
|
||||
break;
|
||||
|
||||
case '*': /* random chars until a separator or number ([ \t.,:;/-0123456789]) */
|
||||
case TIMELIB_FORMAT_SKIP_TO_SEPARATOR: /* random chars until a separator or number ([ \t.,:;/-0123456789]) */
|
||||
timelib_eat_until_separator((char **) &ptr);
|
||||
break;
|
||||
|
||||
case '+': /* allow extra chars in the format */
|
||||
allow_extra = 1;
|
||||
case TIMELIB_FORMAT_ALLOW_EXTRA_CHARACTERS: /* allow extra chars in the format */
|
||||
allow_extra = true;
|
||||
break;
|
||||
case TIMELIB_FORMAT_YEAR_ISO:
|
||||
if ((iso_year = timelib_get_nr((char **) &ptr, 4)) == TIMELIB_UNSET) {
|
||||
add_pbf_error(s, TIMELIB_ERR_NO_FOUR_DIGIT_YEAR_ISO, "A four digit ISO year could not be found", string, begin);
|
||||
}
|
||||
break;
|
||||
case TIMELIB_FORMAT_WEEK_OF_YEAR_ISO:
|
||||
if ((iso_week_of_year = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
|
||||
add_pbf_error(s, TIMELIB_ERR_NO_TWO_DIGIT_WEEK, "A two digit ISO week could not be found", string, begin);
|
||||
}
|
||||
/* Range is 1 - 53 for ISO week of year */
|
||||
if (iso_week_of_year < 1 || iso_week_of_year > 53) {
|
||||
add_pbf_error(s, TIMELIB_ERR_INVALID_WEEK, "ISO Week must be between 1 and 53", string, begin);
|
||||
}
|
||||
break;
|
||||
case TIMELIB_FORMAT_DAY_OF_WEEK_ISO:
|
||||
if ((iso_day_of_week = timelib_get_nr((char **) &ptr, 1)) == TIMELIB_UNSET) {
|
||||
add_pbf_error(s, TIMELIB_ERR_NO_DAY_OF_WEEK, "A single digit day of week could not be found", string, begin);
|
||||
}
|
||||
if (iso_day_of_week < 1 || iso_day_of_week > 7) {
|
||||
add_pbf_error(s, TIMELIB_ERR_INVALID_DAY_OF_WEEK, "Day of week must be between 1 and 7", string, begin);
|
||||
}
|
||||
break;
|
||||
case TIMELIB_FORMAT_TIMEZONE_OFFSET: /* timezone */
|
||||
{
|
||||
int tz_not_found;
|
||||
|
||||
s->time->z = timelib_parse_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
|
||||
if (tz_not_found) {
|
||||
add_pbf_error(s, TIMELIB_ERR_TZID_NOT_FOUND, "The timezone could not be found in the database", string, begin);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TIMELIB_FORMAT_TIMEZONE_OFFSET_MINUTES: /* timezone format +/-mmm */
|
||||
s->time->z = timelib_parse_tz_minutes((char **) &ptr, s->time);
|
||||
if (s->time->z == TIMELIB_UNSET) {
|
||||
add_pbf_error(s, TIMELIB_ERR_INVALID_TZ_OFFSET, "Invalid timezone offset in minutes", string, begin);
|
||||
}
|
||||
break;
|
||||
case TIMELIB_FORMAT_LITERAL:
|
||||
default:
|
||||
if (*fptr != *ptr) {
|
||||
add_pbf_error(s, TIMELIB_ERR_WRONG_FORMAT_SEP, "The format separator does not match", string, begin);
|
||||
@ -2182,32 +2350,32 @@ timelib_time *timelib_parse_from_format(char *format, char *string, size_t len,
|
||||
add_pbf_error(s, TIMELIB_ERR_TRAILING_DATA, "Trailing data", string, ptr);
|
||||
}
|
||||
}
|
||||
/* ignore trailing +'s */
|
||||
while (*fptr == '+') {
|
||||
fptr++;
|
||||
}
|
||||
|
||||
if (*fptr) {
|
||||
/* Trailing | and ! specifiers are valid. */
|
||||
/* Trailing reset specifiers are valid. */
|
||||
int done = 0;
|
||||
while (*fptr && !done) {
|
||||
switch (*fptr++) {
|
||||
case '!': /* reset all fields to default */
|
||||
switch (timelib_lookup_format(*fptr, format_map)) {
|
||||
case TIMELIB_FORMAT_RESET_ALL: /* reset all fields to default */
|
||||
timelib_time_reset_fields(s->time);
|
||||
break;
|
||||
|
||||
case '|': /* reset all fields to default when not set */
|
||||
case TIMELIB_FORMAT_RESET_ALL_WHEN_NOT_SET: /* reset all fields to default when not set */
|
||||
timelib_time_reset_unset_fields(s->time);
|
||||
break;
|
||||
case TIMELIB_FORMAT_ALLOW_EXTRA_CHARACTERS:
|
||||
break;
|
||||
|
||||
default:
|
||||
add_pbf_error(s, TIMELIB_ERR_DATA_MISSING, "Data missing", string, ptr);
|
||||
done = 1;
|
||||
}
|
||||
fptr++;
|
||||
}
|
||||
}
|
||||
|
||||
/* clean up a bit */
|
||||
if (s->time->h != TIMELIB_UNSET || s->time->i != TIMELIB_UNSET || s->time->s != TIMELIB_UNSET) {
|
||||
if (s->time->h != TIMELIB_UNSET || s->time->i != TIMELIB_UNSET || s->time->s != TIMELIB_UNSET || s->time->us != TIMELIB_UNSET) {
|
||||
if (s->time->h == TIMELIB_UNSET ) {
|
||||
s->time->h = 0;
|
||||
}
|
||||
@ -2217,6 +2385,31 @@ timelib_time *timelib_parse_from_format(char *format, char *string, size_t len,
|
||||
if (s->time->s == TIMELIB_UNSET ) {
|
||||
s->time->s = 0;
|
||||
}
|
||||
if (s->time->us == TIMELIB_UNSET ) {
|
||||
s->time->us = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for mixing of ISO dates with natural dates. */
|
||||
if (s->time->y != TIMELIB_UNSET && (iso_week_of_year != TIMELIB_UNSET || iso_year != TIMELIB_UNSET || iso_day_of_week != TIMELIB_UNSET)) {
|
||||
add_pbf_error(s, TIMELIB_ERR_MIX_ISO_WITH_NATURAL, "Mixing of ISO dates with natural dates is not allowed", string, ptr);
|
||||
}
|
||||
if (iso_year != TIMELIB_UNSET && (s->time->y != TIMELIB_UNSET || s->time->m != TIMELIB_UNSET || s->time->d != TIMELIB_UNSET)) {
|
||||
add_pbf_error(s, TIMELIB_ERR_MIX_ISO_WITH_NATURAL, "Mixing of ISO dates with natural dates is not allowed", string, ptr);
|
||||
}
|
||||
|
||||
/* Convert ISO values */
|
||||
if (iso_year != TIMELIB_UNSET) {
|
||||
/* Default week of year and day of week to 1. */
|
||||
if (iso_week_of_year == TIMELIB_UNSET) {
|
||||
iso_week_of_year = 1;
|
||||
}
|
||||
if (iso_day_of_week == TIMELIB_UNSET) {
|
||||
iso_day_of_week = 1;
|
||||
}
|
||||
timelib_date_from_isodate(iso_year, iso_week_of_year, iso_day_of_week, &s->time->y, &s->time->m, &s->time->d);
|
||||
} else if (iso_week_of_year != TIMELIB_UNSET || iso_day_of_week != TIMELIB_UNSET) {
|
||||
add_pbf_warning(s, TIMELIB_WARN_INVALID_DATE, "The parsed date was invalid", string, ptr);
|
||||
}
|
||||
|
||||
/* do funky checking whether the parsed time was valid time */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Generated by re2c 0.15.3 on Wed Jan 31 11:51:44 2018 */
|
||||
#line 1 "ext/date/lib/parse_iso_intervals.re"
|
||||
/* Generated by re2c 0.15.3 on Tue Oct 9 10:50:29 2018 */
|
||||
#line 1 "parse_iso_intervals.re"
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
@ -176,7 +176,7 @@ static int scan(Scanner *s)
|
||||
std:
|
||||
s->tok = cursor;
|
||||
s->len = 0;
|
||||
#line 204 "ext/date/lib/parse_iso_intervals.re"
|
||||
#line 204 "parse_iso_intervals.re"
|
||||
|
||||
|
||||
|
||||
@ -185,38 +185,38 @@ std:
|
||||
YYCTYPE yych;
|
||||
unsigned int yyaccept = 0;
|
||||
static const unsigned char yybm[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
128, 128, 128, 128, 128, 128, 128, 128,
|
||||
128, 128, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
128, 128, 128, 128, 128, 128, 128, 128,
|
||||
128, 128, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
YYDEBUG(0, *YYCURSOR);
|
||||
if ((YYLIMIT - YYCURSOR) < 20) YYFILL(20);
|
||||
@ -249,7 +249,7 @@ std:
|
||||
if (yych <= '9') goto yy98;
|
||||
yy3:
|
||||
YYDEBUG(3, *YYCURSOR);
|
||||
#line 317 "ext/date/lib/parse_iso_intervals.re"
|
||||
#line 317 "parse_iso_intervals.re"
|
||||
{
|
||||
add_error(s, "Unexpected character");
|
||||
goto std;
|
||||
@ -271,7 +271,7 @@ yy5:
|
||||
if (yych == 'T') goto yy14;
|
||||
yy6:
|
||||
YYDEBUG(6, *YYCURSOR);
|
||||
#line 244 "ext/date/lib/parse_iso_intervals.re"
|
||||
#line 244 "parse_iso_intervals.re"
|
||||
{
|
||||
timelib_sll nr;
|
||||
int in_time = 0;
|
||||
@ -317,7 +317,7 @@ yy7:
|
||||
YYDEBUG(7, *YYCURSOR);
|
||||
++YYCURSOR;
|
||||
YYDEBUG(8, *YYCURSOR);
|
||||
#line 306 "ext/date/lib/parse_iso_intervals.re"
|
||||
#line 306 "parse_iso_intervals.re"
|
||||
{
|
||||
goto std;
|
||||
}
|
||||
@ -326,7 +326,7 @@ yy9:
|
||||
YYDEBUG(9, *YYCURSOR);
|
||||
++YYCURSOR;
|
||||
YYDEBUG(10, *YYCURSOR);
|
||||
#line 311 "ext/date/lib/parse_iso_intervals.re"
|
||||
#line 311 "parse_iso_intervals.re"
|
||||
{
|
||||
s->pos = cursor; s->line++;
|
||||
goto std;
|
||||
@ -661,7 +661,7 @@ yy51:
|
||||
YYDEBUG(57, *YYCURSOR);
|
||||
++YYCURSOR;
|
||||
YYDEBUG(58, *YYCURSOR);
|
||||
#line 286 "ext/date/lib/parse_iso_intervals.re"
|
||||
#line 286 "parse_iso_intervals.re"
|
||||
{
|
||||
DEBUG_OUTPUT("combinedrep");
|
||||
TIMELIB_INIT;
|
||||
@ -809,7 +809,7 @@ yy83:
|
||||
YYDEBUG(83, *YYCURSOR);
|
||||
++YYCURSOR;
|
||||
YYDEBUG(84, *YYCURSOR);
|
||||
#line 220 "ext/date/lib/parse_iso_intervals.re"
|
||||
#line 220 "parse_iso_intervals.re"
|
||||
{
|
||||
timelib_time *current;
|
||||
|
||||
@ -910,7 +910,7 @@ yy98:
|
||||
if (yych <= '9') goto yy98;
|
||||
yy100:
|
||||
YYDEBUG(100, *YYCURSOR);
|
||||
#line 209 "ext/date/lib/parse_iso_intervals.re"
|
||||
#line 209 "parse_iso_intervals.re"
|
||||
{
|
||||
DEBUG_OUTPUT("recurrences");
|
||||
TIMELIB_INIT;
|
||||
@ -922,7 +922,7 @@ yy100:
|
||||
}
|
||||
#line 924 "<stdout>"
|
||||
}
|
||||
#line 321 "ext/date/lib/parse_iso_intervals.re"
|
||||
#line 321 "parse_iso_intervals.re"
|
||||
|
||||
}
|
||||
#ifdef PHP_WIN32
|
||||
|
@ -585,7 +585,7 @@ static ttinfo* fetch_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, timelib
|
||||
return &(tz->type[tz->trans_idx[j]]);
|
||||
}
|
||||
|
||||
/* In all other cases we loop through the available transtion times to find
|
||||
/* In all other cases we loop through the available transition times to find
|
||||
* the correct entry */
|
||||
for (i = 0; i < tz->bit32.timecnt; i++) {
|
||||
if (ts < tz->trans[i]) {
|
||||
|
@ -30,6 +30,7 @@
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <limits.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
@ -264,6 +265,16 @@ typedef struct _timelib_abbr_info {
|
||||
#define TIMELIB_ERR_WRONG_FORMAT_SEP 0x219
|
||||
#define TIMELIB_ERR_TRAILING_DATA 0x21a
|
||||
#define TIMELIB_ERR_DATA_MISSING 0x21b
|
||||
#define TIMELIB_ERR_NO_THREE_DIGIT_MILLISECOND 0x21c
|
||||
#define TIMELIB_ERR_NO_FOUR_DIGIT_YEAR_ISO 0x21d
|
||||
#define TIMELIB_ERR_NO_TWO_DIGIT_WEEK 0x21e
|
||||
#define TIMELIB_ERR_INVALID_WEEK 0x21f
|
||||
#define TIMELIB_ERR_NO_DAY_OF_WEEK 0x220
|
||||
#define TIMELIB_ERR_INVALID_DAY_OF_WEEK 0x221
|
||||
#define TIMELIB_ERR_INVALID_SPECIFIER 0x222
|
||||
#define TIMELIB_ERR_INVALID_TZ_OFFSET 0x223
|
||||
#define TIMELIB_ERR_FORMAT_LITERAL_MISMATCH 0x224
|
||||
#define TIMELIB_ERR_MIX_ISO_WITH_NATURAL 0x225
|
||||
|
||||
#define TIMELIB_ZONETYPE_OFFSET 1
|
||||
#define TIMELIB_ZONETYPE_ABBR 2
|
||||
@ -310,9 +321,9 @@ typedef struct _timelib_tzdb {
|
||||
# define timelib_free free
|
||||
#endif
|
||||
|
||||
#define TIMELIB_VERSION 201706
|
||||
#define TIMELIB_EXTENDED_VERSION 20170600
|
||||
#define TIMELIB_ASCII_VERSION "2017.06"
|
||||
#define TIMELIB_VERSION 201801
|
||||
#define TIMELIB_EXTENDED_VERSION 20180002
|
||||
#define TIMELIB_ASCII_VERSION "2018.01alpha2"
|
||||
|
||||
#define TIMELIB_NONE 0x00
|
||||
#define TIMELIB_OVERRIDE_TIME 0x01
|
||||
@ -334,6 +345,60 @@ typedef struct _timelib_tzdb {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum _timelib_format_specifier_code {
|
||||
TIMELIB_FORMAT_ALLOW_EXTRA_CHARACTERS = 0,
|
||||
TIMELIB_FORMAT_ANY_SEPARATOR,
|
||||
TIMELIB_FORMAT_DAY_TWO_DIGIT,
|
||||
TIMELIB_FORMAT_DAY_TWO_DIGIT_PADDED,
|
||||
TIMELIB_FORMAT_DAY_OF_WEEK_ISO,
|
||||
TIMELIB_FORMAT_DAY_OF_WEEK,
|
||||
TIMELIB_FORMAT_DAY_OF_YEAR,
|
||||
TIMELIB_FORMAT_DAY_SUFFIX,
|
||||
TIMELIB_FORMAT_END,
|
||||
TIMELIB_FORMAT_EPOCH_SECONDS,
|
||||
TIMELIB_FORMAT_ESCAPE,
|
||||
TIMELIB_FORMAT_HOUR_TWO_DIGIT_12_MAX,
|
||||
TIMELIB_FORMAT_HOUR_TWO_DIGIT_12_MAX_PADDED,
|
||||
TIMELIB_FORMAT_HOUR_TWO_DIGIT_24_MAX,
|
||||
TIMELIB_FORMAT_HOUR_TWO_DIGIT_24_MAX_PADDED,
|
||||
TIMELIB_FORMAT_LITERAL,
|
||||
TIMELIB_FORMAT_MERIDIAN,
|
||||
TIMELIB_FORMAT_MICROSECOND_SIX_DIGIT,
|
||||
TIMELIB_FORMAT_MILLISECOND_THREE_DIGIT,
|
||||
TIMELIB_FORMAT_MINUTE_TWO_DIGIT,
|
||||
TIMELIB_FORMAT_MONTH_TWO_DIGIT,
|
||||
TIMELIB_FORMAT_MONTH_TWO_DIGIT_PADDED,
|
||||
TIMELIB_FORMAT_RANDOM_CHAR,
|
||||
TIMELIB_FORMAT_RESET_ALL,
|
||||
TIMELIB_FORMAT_RESET_ALL_WHEN_NOT_SET,
|
||||
TIMELIB_FORMAT_SECOND_TWO_DIGIT,
|
||||
TIMELIB_FORMAT_SEPARATOR,
|
||||
TIMELIB_FORMAT_SKIP_TO_SEPARATOR,
|
||||
TIMELIB_FORMAT_TEXTUAL_DAY_3_LETTER,
|
||||
TIMELIB_FORMAT_TEXTUAL_DAY_FULL,
|
||||
TIMELIB_FORMAT_TEXTUAL_MONTH_3_LETTER,
|
||||
TIMELIB_FORMAT_TEXTUAL_MONTH_FULL,
|
||||
TIMELIB_FORMAT_TIMEZONE_OFFSET,
|
||||
TIMELIB_FORMAT_TIMEZONE_OFFSET_MINUTES,
|
||||
TIMELIB_FORMAT_WEEK_OF_YEAR_ISO,
|
||||
TIMELIB_FORMAT_WEEK_OF_YEAR,
|
||||
TIMELIB_FORMAT_WHITESPACE,
|
||||
TIMELIB_FORMAT_YEAR_TWO_DIGIT,
|
||||
TIMELIB_FORMAT_YEAR_FOUR_DIGIT,
|
||||
TIMELIB_FORMAT_YEAR_ISO
|
||||
} timelib_format_specifier_code;
|
||||
|
||||
typedef struct _timelib_format_specifier {
|
||||
char specifier;
|
||||
timelib_format_specifier_code code;
|
||||
} timelib_format_specifier;
|
||||
|
||||
typedef struct _timelib_format_config {
|
||||
const timelib_format_specifier *format_map;
|
||||
/* Format speciifiers must be preceded by 'prefix_char' if not '\0'. */
|
||||
char prefix_char;
|
||||
} timelib_format_config;
|
||||
|
||||
/* Function pointers */
|
||||
typedef timelib_tzinfo* (*timelib_tz_get_wrapper)(char *tzname, const timelib_tzdb *tzdb, int *error_code);
|
||||
|
||||
@ -416,6 +481,20 @@ timelib_time *timelib_strtotime(char *s, size_t len, timelib_error_container **e
|
||||
*/
|
||||
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);
|
||||
|
||||
/* Parses the date/time string in 's' with length 'len' into the constituent
|
||||
* parts of timelib_time* according to the format in 'format' with format
|
||||
* specifier configuration 'format_config'.
|
||||
*
|
||||
* 'format_map' is an array of pairs, with the first element being the format
|
||||
* specifier as a character and the second element corresponds to the
|
||||
* representation of the specifier from the enum list
|
||||
* 'timelib_format_specifier_code'.
|
||||
*
|
||||
* Note: 'format_map' must be terminated with specifier '\0' to indicate to the
|
||||
* parser that there are no more format specifiers in the list.
|
||||
*/
|
||||
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);
|
||||
|
||||
/* 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):
|
||||
@ -488,8 +567,8 @@ timelib_long timelib_parse_zone(char **ptr, int *dst, timelib_time *t, int *tz_n
|
||||
*/
|
||||
void timelib_strtointerval(char *s, size_t len,
|
||||
timelib_time **begin, timelib_time **end,
|
||||
timelib_rel_time **period, int *recurrences,
|
||||
timelib_error_container **errors);
|
||||
timelib_rel_time **period, int *recurrences,
|
||||
timelib_error_container **errors);
|
||||
|
||||
|
||||
/* From tm2unixtime.c */
|
||||
@ -630,7 +709,7 @@ int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz);
|
||||
* 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');
|
||||
* 'transition_time');
|
||||
*/
|
||||
timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz);
|
||||
|
||||
|
@ -155,9 +155,9 @@
|
||||
{ "bmt", 0, 25632, "Asia/Jakarta" },
|
||||
{ "bmt", 0, 6264, "Europe/Bucharest" },
|
||||
{ "bmt", 0, 6264, "Europe/Chisinau" },
|
||||
{ "bost", 1, -12756, "America/La_Paz" },
|
||||
{ "bst", 1, 3600, "Europe/London" },
|
||||
{ "bst", 0, 3600, "Europe/London" },
|
||||
{ "bst", 1, -12756, "America/La_Paz" },
|
||||
{ "bst", 0, -39600, "America/Adak" },
|
||||
{ "bst", 0, -39600, "America/Atka" },
|
||||
{ "bst", 0, -39600, "America/Nome" },
|
||||
@ -672,6 +672,9 @@
|
||||
{ "gmt", 0, 0, "Europe/Jersey" },
|
||||
{ "gmt", 0, 0, "Europe/London" },
|
||||
{ "gmt", 0, 0, "GB" },
|
||||
{ "gmt", 1, 0, "Europe/Bratislava" },
|
||||
{ "gmt", 1, 0, "Europe/Dublin" },
|
||||
{ "gmt", 1, 0, "Europe/Prague" },
|
||||
{ "gst", 0, 36000, "Pacific/Guam" },
|
||||
{ "gst", 0, 36000, "Pacific/Saipan" },
|
||||
{ "hdt", 1, -34200, "Pacific/Honolulu" },
|
||||
@ -728,8 +731,8 @@
|
||||
{ "kdt", 1, 34200, "ROK" },
|
||||
{ "kdt", 1, 36000, "ROK" },
|
||||
{ "kmt", 0, 5736, "Europe/Vilnius" },
|
||||
{ "kmt", 0, -18431, "America/Grand_Turk" },
|
||||
{ "kmt", 0, -18431, "America/Jamaica" },
|
||||
{ "kmt", 0, -18430, "America/Grand_Turk" },
|
||||
{ "kmt", 0, -18430, "America/Jamaica" },
|
||||
{ "kmt", 0, 7324, "Europe/Kiev" },
|
||||
{ "kst", 0, 30600, "Asia/Seoul" },
|
||||
{ "kst", 0, 32400, "Asia/Pyongyang" },
|
||||
@ -764,7 +767,7 @@
|
||||
{ "mdt", 1, -21600, "Mexico/BajaSur" },
|
||||
{ "mmt", 0, 9017, "Europe/Moscow" },
|
||||
{ "mmt", 0, 9079, "Europe/Moscow" },
|
||||
{ "mmt", 0, -13484, "America/Montevideo" },
|
||||
{ "mmt", 0, -13491, "America/Montevideo" },
|
||||
{ "mmt", 0, -20712, "America/Managua" },
|
||||
{ "mmt", 0, -2588, "Africa/Monrovia" },
|
||||
{ "mmt", 0, -2670, "Africa/Monrovia" },
|
||||
@ -1042,7 +1045,8 @@
|
||||
{ "wat", 0, 3600, "Africa/Ndjamena" },
|
||||
{ "wat", 0, 3600, "Africa/Niamey" },
|
||||
{ "wat", 0, 3600, "Africa/Porto-Novo" },
|
||||
{ "wat", 0, 3600, "Africa/Windhoek" },
|
||||
{ "wat", 0, 3600, "Africa/Sao_Tome" },
|
||||
{ "wat", 1, 3600, "Africa/Windhoek" },
|
||||
{ "wemt", 1, 7200, "Europe/Lisbon" },
|
||||
{ "wemt", 1, 7200, "Europe/Madrid" },
|
||||
{ "wemt", 1, 7200, "Europe/Monaco" },
|
||||
|
@ -39,7 +39,7 @@ static void do_range_limit_fraction(timelib_sll *fraction, timelib_sll *seconds)
|
||||
*fraction += 1000000;
|
||||
*seconds -= 1;
|
||||
}
|
||||
if (*fraction > 1000000) {
|
||||
if (*fraction >= 1000000) {
|
||||
*fraction -= 1000000;
|
||||
*seconds += 1;
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts)
|
||||
}
|
||||
TIMELIB_DEBUG(printf("A: ts=%lld, year=%lld, month=%lld, day=%lld,", ts, cur_year, i + 1, tmp_days - months[i]););
|
||||
|
||||
/* That was the date, now we do the tiiiime */
|
||||
/* That was the date, now we do the time */
|
||||
hours = remainder / 3600;
|
||||
minutes = (remainder - hours * 3600) / 60;
|
||||
seconds = remainder % 60;
|
||||
@ -251,7 +251,7 @@ void timelib_set_timezone(timelib_time *t, timelib_tzinfo *tz)
|
||||
|
||||
/* Converts the time stored in the struct to localtime if localtime = true,
|
||||
* otherwise it converts it to gmttime. This is only done when necessary
|
||||
* ofcourse. */
|
||||
* of course. */
|
||||
int timelib_apply_localtime(timelib_time *t, unsigned int localtime)
|
||||
{
|
||||
if (localtime) {
|
||||
|
Loading…
Reference in New Issue
Block a user