mirror of
https://github.com/php/php-src.git
synced 2024-12-03 23:05:57 +08:00
5b2ce47f2e
- Fixed bug #52062 (large timestamps with DateTime::getTimestamp and DateTime::setTimestamp). - Fixed bug #51994 (date_parse_from_format is parsing invalid date using 'yz' format). - Fixed bug #51223 (Seg fault while creating (by unserialization) DatePeriod).
2296 lines
61 KiB
C
2296 lines
61 KiB
C
/*
|
|
+----------------------------------------------------------------------+
|
|
| PHP Version 5 |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 1997-2010 The PHP Group |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 3.01 of the PHP license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available through the world-wide-web at the following url: |
|
|
| http://www.php.net/license/3_01.txt |
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
| Authors: Derick Rethans <derick@derickrethans.nl> |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
|
|
/* $Id$ */
|
|
|
|
#include "timelib.h"
|
|
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <math.h>
|
|
#include <assert.h>
|
|
|
|
#ifdef HAVE_STDLIB_H
|
|
#include <stdlib.h>
|
|
#endif
|
|
#ifdef HAVE_STRING_H
|
|
#include <string.h>
|
|
#else
|
|
#include <strings.h>
|
|
#endif
|
|
|
|
#if defined(_MSC_VER)
|
|
# define strtoll(s, f, b) _atoi64(s)
|
|
#elif !defined(HAVE_STRTOLL)
|
|
# if defined(HAVE_ATOLL)
|
|
# define strtoll(s, f, b) atoll(s)
|
|
# else
|
|
# define strtoll(s, f, b) strtol(s, f, b)
|
|
# endif
|
|
#endif
|
|
|
|
#define TIMELIB_UNSET -99999
|
|
|
|
#define TIMELIB_SECOND 1
|
|
#define TIMELIB_MINUTE 2
|
|
#define TIMELIB_HOUR 3
|
|
#define TIMELIB_DAY 4
|
|
#define TIMELIB_MONTH 5
|
|
#define TIMELIB_YEAR 6
|
|
#define TIMELIB_WEEKDAY 7
|
|
#define TIMELIB_SPECIAL 8
|
|
|
|
#define EOI 257
|
|
#define TIME 258
|
|
#define DATE 259
|
|
|
|
#define TIMELIB_XMLRPC_SOAP 260
|
|
#define TIMELIB_TIME12 261
|
|
#define TIMELIB_TIME24 262
|
|
#define TIMELIB_GNU_NOCOLON 263
|
|
#define TIMELIB_GNU_NOCOLON_TZ 264
|
|
#define TIMELIB_ISO_NOCOLON 265
|
|
|
|
#define TIMELIB_AMERICAN 266
|
|
#define TIMELIB_ISO_DATE 267
|
|
#define TIMELIB_DATE_FULL 268
|
|
#define TIMELIB_DATE_TEXT 269
|
|
#define TIMELIB_DATE_NOCOLON 270
|
|
#define TIMELIB_PG_YEARDAY 271
|
|
#define TIMELIB_PG_TEXT 272
|
|
#define TIMELIB_PG_REVERSE 273
|
|
#define TIMELIB_CLF 274
|
|
#define TIMELIB_DATE_NO_DAY 275
|
|
#define TIMELIB_SHORTDATE_WITH_TIME 276
|
|
#define TIMELIB_DATE_FULL_POINTED 277
|
|
#define TIMELIB_TIME24_WITH_ZONE 278
|
|
#define TIMELIB_ISO_WEEK 279
|
|
#define TIMELIB_LF_DAY_OF_MONTH 280
|
|
#define TIMELIB_WEEK_DAY_OF_MONTH 281
|
|
|
|
#define TIMELIB_TIMEZONE 300
|
|
#define TIMELIB_AGO 301
|
|
|
|
#define TIMELIB_RELATIVE 310
|
|
|
|
#define TIMELIB_ERROR 999
|
|
|
|
/* Some compilers like AIX, defines uchar in sys/types.h */
|
|
#undef uchar
|
|
typedef unsigned char uchar;
|
|
|
|
#define BSIZE 8192
|
|
|
|
#define YYCTYPE uchar
|
|
#define YYCURSOR cursor
|
|
#define YYLIMIT s->lim
|
|
#define YYMARKER s->ptr
|
|
#define YYFILL(n) return EOI;
|
|
|
|
#define RET(i) {s->cur = cursor; return i;}
|
|
|
|
#define timelib_string_free free
|
|
|
|
#define TIMELIB_HAVE_TIME() { if (s->time->have_time) { add_error(s, "Double time specification"); timelib_string_free(str); return TIMELIB_ERROR; } else { s->time->have_time = 1; s->time->h = 0; s->time->i = 0; s->time->s = 0; s->time->f = 0; } }
|
|
#define TIMELIB_UNHAVE_TIME() { s->time->have_time = 0; s->time->h = 0; s->time->i = 0; s->time->s = 0; s->time->f = 0; }
|
|
#define TIMELIB_HAVE_DATE() { if (s->time->have_date) { add_error(s, "Double date specification"); timelib_string_free(str); return TIMELIB_ERROR; } else { s->time->have_date = 1; } }
|
|
#define TIMELIB_UNHAVE_DATE() { s->time->have_date = 0; s->time->d = 0; s->time->m = 0; s->time->y = 0; }
|
|
#define TIMELIB_HAVE_RELATIVE() { s->time->have_relative = 1; }
|
|
#define TIMELIB_HAVE_WEEKDAY_RELATIVE() { s->time->have_relative = 1; s->time->relative.have_weekday_relative = 1; }
|
|
#define TIMELIB_HAVE_SPECIAL_RELATIVE() { s->time->have_relative = 1; s->time->relative.have_special_relative = 1; }
|
|
#define TIMELIB_HAVE_TZ() { s->cur = cursor; if (s->time->have_zone) { s->time->have_zone > 1 ? add_error(s, "Double timezone specification") : add_warning(s, "Double timezone specification"); timelib_string_free(str); s->time->have_zone++; return TIMELIB_ERROR; } else { s->time->have_zone++; } }
|
|
|
|
#define TIMELIB_INIT s->cur = cursor; str = timelib_string(s); ptr = str
|
|
#define TIMELIB_DEINIT timelib_string_free(str)
|
|
#define TIMELIB_ADJUST_RELATIVE_WEEKDAY() if (in->time.have_weekday_relative && (in.rel.d > 0)) { in.rel.d -= 7; }
|
|
|
|
#define TIMELIB_PROCESS_YEAR(x, l) { \
|
|
if (((x) == TIMELIB_UNSET) || ((l) >= 4)) { \
|
|
/* (x) = 0; */ \
|
|
} else if ((x) < 100) { \
|
|
if ((x) < 70) { \
|
|
(x) += 2000; \
|
|
} else { \
|
|
(x) += 1900; \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
#ifdef DEBUG_PARSER
|
|
#define DEBUG_OUTPUT(s) printf("%s\n", s);
|
|
#define YYDEBUG(s,c) { if (s != -1) { printf("state: %d ", s); printf("[%c]\n", c); } }
|
|
#else
|
|
#define DEBUG_OUTPUT(s)
|
|
#define YYDEBUG(s,c)
|
|
#endif
|
|
|
|
#include "timelib_structs.h"
|
|
|
|
typedef struct timelib_elems {
|
|
unsigned int c; /* Number of elements */
|
|
char **v; /* Values */
|
|
} timelib_elems;
|
|
|
|
typedef struct Scanner {
|
|
int fd;
|
|
uchar *lim, *str, *ptr, *cur, *tok, *pos;
|
|
unsigned int line, len;
|
|
struct timelib_error_container *errors;
|
|
|
|
struct timelib_time *time;
|
|
const timelib_tzdb *tzdb;
|
|
} Scanner;
|
|
|
|
typedef struct _timelib_lookup_table {
|
|
const char *name;
|
|
int type;
|
|
int value;
|
|
} timelib_lookup_table;
|
|
|
|
typedef struct _timelib_relunit {
|
|
const char *name;
|
|
int unit;
|
|
int multiplier;
|
|
} timelib_relunit;
|
|
|
|
#define HOUR(a) (int)(a * 60)
|
|
|
|
/* The timezone table. */
|
|
const static timelib_tz_lookup_table timelib_timezone_lookup[] = {
|
|
#include "timezonemap.h"
|
|
{ NULL, 0, 0, NULL },
|
|
};
|
|
|
|
const static timelib_tz_lookup_table timelib_timezone_fallbackmap[] = {
|
|
#include "fallbackmap.h"
|
|
{ NULL, 0, 0, NULL },
|
|
};
|
|
|
|
const static timelib_tz_lookup_table timelib_timezone_utc[] = {
|
|
{ "utc", 0, 0, "UTC" },
|
|
};
|
|
|
|
static timelib_relunit const timelib_relunit_lookup[] = {
|
|
{ "sec", TIMELIB_SECOND, 1 },
|
|
{ "secs", TIMELIB_SECOND, 1 },
|
|
{ "second", TIMELIB_SECOND, 1 },
|
|
{ "seconds", TIMELIB_SECOND, 1 },
|
|
{ "min", TIMELIB_MINUTE, 1 },
|
|
{ "mins", TIMELIB_MINUTE, 1 },
|
|
{ "minute", TIMELIB_MINUTE, 1 },
|
|
{ "minutes", TIMELIB_MINUTE, 1 },
|
|
{ "hour", TIMELIB_HOUR, 1 },
|
|
{ "hours", TIMELIB_HOUR, 1 },
|
|
{ "day", TIMELIB_DAY, 1 },
|
|
{ "days", TIMELIB_DAY, 1 },
|
|
{ "week", TIMELIB_DAY, 7 },
|
|
{ "weeks", TIMELIB_DAY, 7 },
|
|
{ "fortnight", TIMELIB_DAY, 14 },
|
|
{ "fortnights", TIMELIB_DAY, 14 },
|
|
{ "forthnight", TIMELIB_DAY, 14 },
|
|
{ "forthnights", TIMELIB_DAY, 14 },
|
|
{ "month", TIMELIB_MONTH, 1 },
|
|
{ "months", TIMELIB_MONTH, 1 },
|
|
{ "year", TIMELIB_YEAR, 1 },
|
|
{ "years", TIMELIB_YEAR, 1 },
|
|
|
|
{ "monday", TIMELIB_WEEKDAY, 1 },
|
|
{ "mon", TIMELIB_WEEKDAY, 1 },
|
|
{ "tuesday", TIMELIB_WEEKDAY, 2 },
|
|
{ "tue", TIMELIB_WEEKDAY, 2 },
|
|
{ "wednesday", TIMELIB_WEEKDAY, 3 },
|
|
{ "wed", TIMELIB_WEEKDAY, 3 },
|
|
{ "thursday", TIMELIB_WEEKDAY, 4 },
|
|
{ "thu", TIMELIB_WEEKDAY, 4 },
|
|
{ "friday", TIMELIB_WEEKDAY, 5 },
|
|
{ "fri", TIMELIB_WEEKDAY, 5 },
|
|
{ "saturday", TIMELIB_WEEKDAY, 6 },
|
|
{ "sat", TIMELIB_WEEKDAY, 6 },
|
|
{ "sunday", TIMELIB_WEEKDAY, 0 },
|
|
{ "sun", TIMELIB_WEEKDAY, 0 },
|
|
|
|
{ "weekday", TIMELIB_SPECIAL, TIMELIB_SPECIAL_WEEKDAY },
|
|
{ "weekdays", TIMELIB_SPECIAL, TIMELIB_SPECIAL_WEEKDAY },
|
|
{ NULL, 0, 0 }
|
|
};
|
|
|
|
/* The relative text table. */
|
|
static timelib_lookup_table const timelib_reltext_lookup[] = {
|
|
{ "first", 0, 1 },
|
|
{ "next", 0, 1 },
|
|
{ "second", 0, 2 },
|
|
{ "third", 0, 3 },
|
|
{ "fourth", 0, 4 },
|
|
{ "fifth", 0, 5 },
|
|
{ "sixth", 0, 6 },
|
|
{ "seventh", 0, 7 },
|
|
{ "eight", 0, 8 },
|
|
{ "eighth", 0, 8 },
|
|
{ "ninth", 0, 9 },
|
|
{ "tenth", 0, 10 },
|
|
{ "eleventh", 0, 11 },
|
|
{ "twelfth", 0, 12 },
|
|
{ "last", 0, -1 },
|
|
{ "previous", 0, -1 },
|
|
{ "this", 1, 0 },
|
|
{ NULL, 1, 0 }
|
|
};
|
|
|
|
/* The month table. */
|
|
static timelib_lookup_table const timelib_month_lookup[] = {
|
|
{ "jan", 0, 1 },
|
|
{ "feb", 0, 2 },
|
|
{ "mar", 0, 3 },
|
|
{ "apr", 0, 4 },
|
|
{ "may", 0, 5 },
|
|
{ "jun", 0, 6 },
|
|
{ "jul", 0, 7 },
|
|
{ "aug", 0, 8 },
|
|
{ "sep", 0, 9 },
|
|
{ "sept", 0, 9 },
|
|
{ "oct", 0, 10 },
|
|
{ "nov", 0, 11 },
|
|
{ "dec", 0, 12 },
|
|
{ "i", 0, 1 },
|
|
{ "ii", 0, 2 },
|
|
{ "iii", 0, 3 },
|
|
{ "iv", 0, 4 },
|
|
{ "v", 0, 5 },
|
|
{ "vi", 0, 6 },
|
|
{ "vii", 0, 7 },
|
|
{ "viii", 0, 8 },
|
|
{ "ix", 0, 9 },
|
|
{ "x", 0, 10 },
|
|
{ "xi", 0, 11 },
|
|
{ "xii", 0, 12 },
|
|
|
|
{ "january", 0, 1 },
|
|
{ "february", 0, 2 },
|
|
{ "march", 0, 3 },
|
|
{ "april", 0, 4 },
|
|
{ "may", 0, 5 },
|
|
{ "june", 0, 6 },
|
|
{ "july", 0, 7 },
|
|
{ "august", 0, 8 },
|
|
{ "september", 0, 9 },
|
|
{ "october", 0, 10 },
|
|
{ "november", 0, 11 },
|
|
{ "december", 0, 12 },
|
|
{ NULL, 0, 0 }
|
|
};
|
|
|
|
#if 0
|
|
static char* timelib_ltrim(char *s)
|
|
{
|
|
char *ptr = s;
|
|
while (ptr[0] == ' ' || ptr[0] == '\t') {
|
|
ptr++;
|
|
}
|
|
return ptr;
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
uchar *fill(Scanner *s, uchar *cursor){
|
|
if(!s->eof){
|
|
unsigned int cnt = s->tok - s->bot;
|
|
if(cnt){
|
|
memcpy(s->bot, s->tok, s->lim - s->tok);
|
|
s->tok = s->bot;
|
|
s->ptr -= cnt;
|
|
cursor -= cnt;
|
|
s->pos -= cnt;
|
|
s->lim -= cnt;
|
|
}
|
|
if((s->top - s->lim) < BSIZE){
|
|
uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
|
|
memcpy(buf, s->tok, s->lim - s->tok);
|
|
s->tok = buf;
|
|
s->ptr = &buf[s->ptr - s->bot];
|
|
cursor = &buf[cursor - s->bot];
|
|
s->pos = &buf[s->pos - s->bot];
|
|
s->lim = &buf[s->lim - s->bot];
|
|
s->top = &s->lim[BSIZE];
|
|
free(s->bot);
|
|
s->bot = buf;
|
|
}
|
|
if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){
|
|
s->eof = &s->lim[cnt]; *(s->eof)++ = '\n';
|
|
}
|
|
s->lim += cnt;
|
|
}
|
|
return cursor;
|
|
}
|
|
#endif
|
|
|
|
static void add_warning(Scanner *s, char *error)
|
|
{
|
|
s->errors->warning_count++;
|
|
s->errors->warning_messages = realloc(s->errors->warning_messages, s->errors->warning_count * sizeof(timelib_error_message));
|
|
s->errors->warning_messages[s->errors->warning_count - 1].position = s->tok ? s->tok - s->str : 0;
|
|
s->errors->warning_messages[s->errors->warning_count - 1].character = s->tok ? *s->tok : 0;
|
|
s->errors->warning_messages[s->errors->warning_count - 1].message = strdup(error);
|
|
}
|
|
|
|
static void add_error(Scanner *s, char *error)
|
|
{
|
|
s->errors->error_count++;
|
|
s->errors->error_messages = realloc(s->errors->error_messages, s->errors->error_count * sizeof(timelib_error_message));
|
|
s->errors->error_messages[s->errors->error_count - 1].position = s->tok ? s->tok - s->str : 0;
|
|
s->errors->error_messages[s->errors->error_count - 1].character = s->tok ? *s->tok : 0;
|
|
s->errors->error_messages[s->errors->error_count - 1].message = strdup(error);
|
|
}
|
|
|
|
static void add_pbf_warning(Scanner *s, char *error, char *sptr, char *cptr)
|
|
{
|
|
s->errors->warning_count++;
|
|
s->errors->warning_messages = realloc(s->errors->warning_messages, s->errors->warning_count * sizeof(timelib_error_message));
|
|
s->errors->warning_messages[s->errors->warning_count - 1].position = cptr - sptr;
|
|
s->errors->warning_messages[s->errors->warning_count - 1].character = *cptr;
|
|
s->errors->warning_messages[s->errors->warning_count - 1].message = strdup(error);
|
|
}
|
|
|
|
static void add_pbf_error(Scanner *s, char *error, char *sptr, char *cptr)
|
|
{
|
|
s->errors->error_count++;
|
|
s->errors->error_messages = realloc(s->errors->error_messages, s->errors->error_count * sizeof(timelib_error_message));
|
|
s->errors->error_messages[s->errors->error_count - 1].position = cptr - sptr;
|
|
s->errors->error_messages[s->errors->error_count - 1].character = *cptr;
|
|
s->errors->error_messages[s->errors->error_count - 1].message = strdup(error);
|
|
}
|
|
|
|
static timelib_sll timelib_meridian(char **ptr, timelib_sll h)
|
|
{
|
|
timelib_sll retval = 0;
|
|
|
|
while (!strchr("AaPp", **ptr)) {
|
|
++*ptr;
|
|
}
|
|
if (**ptr == 'a' || **ptr == 'A') {
|
|
if (h == 12) {
|
|
retval = -12;
|
|
}
|
|
} else if (h != 12) {
|
|
retval = 12;
|
|
}
|
|
++*ptr;
|
|
if (**ptr == '.') {
|
|
*ptr += 3;
|
|
} else {
|
|
++*ptr;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
static timelib_sll timelib_meridian_with_check(char **ptr, timelib_sll h)
|
|
{
|
|
timelib_sll retval = 0;
|
|
|
|
while (!strchr("AaPp", **ptr)) {
|
|
++*ptr;
|
|
}
|
|
if (**ptr == 'a' || **ptr == 'A') {
|
|
if (h == 12) {
|
|
retval = -12;
|
|
}
|
|
} else if (h != 12) {
|
|
retval = 12;
|
|
}
|
|
++*ptr;
|
|
if (**ptr == '.') {
|
|
++*ptr;
|
|
if (**ptr != 'm' && **ptr != 'M') {
|
|
return TIMELIB_UNSET;
|
|
}
|
|
++*ptr;
|
|
if (**ptr != '.' ) {
|
|
return TIMELIB_UNSET;
|
|
}
|
|
++*ptr;
|
|
} else if (**ptr == 'm' || **ptr == 'M') {
|
|
++*ptr;
|
|
} else {
|
|
return TIMELIB_UNSET;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
static char *timelib_string(Scanner *s)
|
|
{
|
|
char *tmp = calloc(1, s->cur - s->tok + 1);
|
|
memcpy(tmp, s->tok, s->cur - s->tok);
|
|
|
|
return tmp;
|
|
}
|
|
|
|
static timelib_sll timelib_get_nr_ex(char **ptr, int max_length, int *scanned_length)
|
|
{
|
|
char *begin, *end, *str;
|
|
timelib_sll tmp_nr = TIMELIB_UNSET;
|
|
int len = 0;
|
|
|
|
while ((**ptr < '0') || (**ptr > '9')) {
|
|
if (**ptr == '\0') {
|
|
return TIMELIB_UNSET;
|
|
}
|
|
++*ptr;
|
|
}
|
|
begin = *ptr;
|
|
while ((**ptr >= '0') && (**ptr <= '9') && len < max_length) {
|
|
++*ptr;
|
|
++len;
|
|
}
|
|
end = *ptr;
|
|
if (scanned_length) {
|
|
*scanned_length = end - begin;
|
|
}
|
|
str = calloc(1, end - begin + 1);
|
|
memcpy(str, begin, end - begin);
|
|
tmp_nr = strtoll(str, NULL, 10);
|
|
free(str);
|
|
return tmp_nr;
|
|
}
|
|
|
|
static timelib_sll timelib_get_nr(char **ptr, int max_length)
|
|
{
|
|
return timelib_get_nr_ex(ptr, max_length, NULL);
|
|
}
|
|
|
|
static void timelib_skip_day_suffix(char **ptr)
|
|
{
|
|
if (isspace(**ptr)) {
|
|
return;
|
|
}
|
|
if (!strncasecmp(*ptr, "nd", 2) || !strncasecmp(*ptr, "rd", 2) ||!strncasecmp(*ptr, "st", 2) || !strncasecmp(*ptr, "th", 2)) {
|
|
*ptr += 2;
|
|
}
|
|
}
|
|
|
|
static double timelib_get_frac_nr(char **ptr, int max_length)
|
|
{
|
|
char *begin, *end, *str;
|
|
double tmp_nr = TIMELIB_UNSET;
|
|
int len = 0;
|
|
|
|
while ((**ptr != '.') && (**ptr != ':') && ((**ptr < '0') || (**ptr > '9'))) {
|
|
if (**ptr == '\0') {
|
|
return TIMELIB_UNSET;
|
|
}
|
|
++*ptr;
|
|
}
|
|
begin = *ptr;
|
|
while (((**ptr == '.') || (**ptr == ':') || ((**ptr >= '0') && (**ptr <= '9'))) && len < max_length) {
|
|
++*ptr;
|
|
++len;
|
|
}
|
|
end = *ptr;
|
|
str = calloc(1, end - begin + 1);
|
|
memcpy(str, begin, end - begin);
|
|
if (str[0] == ':') {
|
|
str[0] = '.';
|
|
}
|
|
tmp_nr = strtod(str, NULL);
|
|
free(str);
|
|
return tmp_nr;
|
|
}
|
|
|
|
static timelib_ull timelib_get_unsigned_nr(char **ptr, int max_length)
|
|
{
|
|
timelib_ull dir = 1;
|
|
|
|
while (((**ptr < '0') || (**ptr > '9')) && (**ptr != '+') && (**ptr != '-')) {
|
|
if (**ptr == '\0') {
|
|
return TIMELIB_UNSET;
|
|
}
|
|
++*ptr;
|
|
}
|
|
|
|
while (**ptr == '+' || **ptr == '-')
|
|
{
|
|
if (**ptr == '-') {
|
|
dir *= -1;
|
|
}
|
|
++*ptr;
|
|
}
|
|
return dir * timelib_get_nr(ptr, max_length);
|
|
}
|
|
|
|
static long timelib_parse_tz_cor(char **ptr)
|
|
{
|
|
char *begin = *ptr, *end;
|
|
long tmp;
|
|
|
|
while (isdigit(**ptr) || **ptr == ':') {
|
|
++*ptr;
|
|
}
|
|
end = *ptr;
|
|
switch (end - begin) {
|
|
case 1:
|
|
case 2:
|
|
return HOUR(strtol(begin, NULL, 10));
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
if (begin[1] == ':') {
|
|
tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 2, NULL, 10);
|
|
return tmp;
|
|
} else if (begin[2] == ':') {
|
|
tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10);
|
|
return tmp;
|
|
} else {
|
|
tmp = strtol(begin, NULL, 10);
|
|
return HOUR(tmp / 100) + tmp % 100;
|
|
}
|
|
case 5:
|
|
tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10);
|
|
return tmp;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static timelib_sll timelib_lookup_relative_text(char **ptr, int *behavior)
|
|
{
|
|
char *word;
|
|
char *begin = *ptr, *end;
|
|
timelib_sll value = 0;
|
|
const timelib_lookup_table *tp;
|
|
|
|
while ((**ptr >= 'A' && **ptr <= 'Z') || (**ptr >= 'a' && **ptr <= 'z')) {
|
|
++*ptr;
|
|
}
|
|
end = *ptr;
|
|
word = calloc(1, end - begin + 1);
|
|
memcpy(word, begin, end - begin);
|
|
|
|
for (tp = timelib_reltext_lookup; tp->name; tp++) {
|
|
if (strcasecmp(word, tp->name) == 0) {
|
|
value = tp->value;
|
|
*behavior = tp->type;
|
|
}
|
|
}
|
|
|
|
free(word);
|
|
return value;
|
|
}
|
|
|
|
static timelib_sll timelib_get_relative_text(char **ptr, int *behavior)
|
|
{
|
|
while (**ptr == ' ' || **ptr == '\t' || **ptr == '-' || **ptr == '/') {
|
|
++*ptr;
|
|
}
|
|
return timelib_lookup_relative_text(ptr, behavior);
|
|
}
|
|
|
|
static long timelib_lookup_month(char **ptr)
|
|
{
|
|
char *word;
|
|
char *begin = *ptr, *end;
|
|
long value = 0;
|
|
const timelib_lookup_table *tp;
|
|
|
|
while ((**ptr >= 'A' && **ptr <= 'Z') || (**ptr >= 'a' && **ptr <= 'z')) {
|
|
++*ptr;
|
|
}
|
|
end = *ptr;
|
|
word = calloc(1, end - begin + 1);
|
|
memcpy(word, begin, end - begin);
|
|
|
|
for (tp = timelib_month_lookup; tp->name; tp++) {
|
|
if (strcasecmp(word, tp->name) == 0) {
|
|
value = tp->value;
|
|
}
|
|
}
|
|
|
|
free(word);
|
|
return value;
|
|
}
|
|
|
|
static long timelib_get_month(char **ptr)
|
|
{
|
|
while (**ptr == ' ' || **ptr == '\t' || **ptr == '-' || **ptr == '.' || **ptr == '/') {
|
|
++*ptr;
|
|
}
|
|
return timelib_lookup_month(ptr);
|
|
}
|
|
|
|
static void timelib_eat_spaces(char **ptr)
|
|
{
|
|
while (**ptr == ' ' || **ptr == '\t') {
|
|
++*ptr;
|
|
}
|
|
}
|
|
|
|
static void timelib_eat_until_separator(char **ptr)
|
|
{
|
|
++*ptr;
|
|
while (strchr(" \t.,:;/-0123456789", **ptr) == NULL) {
|
|
++*ptr;
|
|
}
|
|
}
|
|
|
|
static const timelib_relunit* timelib_lookup_relunit(char **ptr)
|
|
{
|
|
char *word;
|
|
char *begin = *ptr, *end;
|
|
const timelib_relunit *tp, *value = NULL;
|
|
|
|
while (**ptr != '\0' && **ptr != ' ' && **ptr != ',' && **ptr != '\t') {
|
|
++*ptr;
|
|
}
|
|
end = *ptr;
|
|
word = calloc(1, end - begin + 1);
|
|
memcpy(word, begin, end - begin);
|
|
|
|
for (tp = timelib_relunit_lookup; tp->name; tp++) {
|
|
if (strcasecmp(word, tp->name) == 0) {
|
|
value = tp;
|
|
break;
|
|
}
|
|
}
|
|
|
|
free(word);
|
|
return value;
|
|
}
|
|
|
|
static void timelib_set_relative(char **ptr, timelib_sll amount, int behavior, Scanner *s)
|
|
{
|
|
const timelib_relunit* relunit;
|
|
|
|
if (!(relunit = timelib_lookup_relunit(ptr))) {
|
|
return;
|
|
}
|
|
|
|
switch (relunit->unit) {
|
|
case TIMELIB_SECOND: s->time->relative.s += amount * relunit->multiplier; break;
|
|
case TIMELIB_MINUTE: s->time->relative.i += amount * relunit->multiplier; break;
|
|
case TIMELIB_HOUR: s->time->relative.h += amount * relunit->multiplier; break;
|
|
case TIMELIB_DAY: s->time->relative.d += amount * relunit->multiplier; break;
|
|
case TIMELIB_MONTH: s->time->relative.m += amount * relunit->multiplier; break;
|
|
case TIMELIB_YEAR: s->time->relative.y += amount * relunit->multiplier; break;
|
|
|
|
case TIMELIB_WEEKDAY:
|
|
TIMELIB_HAVE_WEEKDAY_RELATIVE();
|
|
TIMELIB_UNHAVE_TIME();
|
|
s->time->relative.d += (amount > 0 ? amount - 1 : amount) * 7;
|
|
s->time->relative.weekday = relunit->multiplier;
|
|
s->time->relative.weekday_behavior = behavior;
|
|
break;
|
|
|
|
case TIMELIB_SPECIAL:
|
|
TIMELIB_HAVE_SPECIAL_RELATIVE();
|
|
TIMELIB_UNHAVE_TIME();
|
|
s->time->relative.special.type = relunit->multiplier;
|
|
s->time->relative.special.amount = amount;
|
|
}
|
|
}
|
|
|
|
const static timelib_tz_lookup_table* zone_search(const char *word, long gmtoffset, int isdst)
|
|
{
|
|
int first_found = 0;
|
|
const timelib_tz_lookup_table *tp, *first_found_elem = NULL;
|
|
const timelib_tz_lookup_table *fmp;
|
|
|
|
if (strcasecmp("utc", word) == 0 || strcasecmp("gmt", word) == 0) {
|
|
return timelib_timezone_utc;
|
|
}
|
|
|
|
for (tp = timelib_timezone_lookup; tp->name; tp++) {
|
|
if (strcasecmp(word, tp->name) == 0) {
|
|
if (!first_found) {
|
|
first_found = 1;
|
|
first_found_elem = tp;
|
|
if (gmtoffset == -1) {
|
|
return tp;
|
|
}
|
|
}
|
|
if (tp->gmtoffset == gmtoffset) {
|
|
return tp;
|
|
}
|
|
}
|
|
}
|
|
if (first_found) {
|
|
return first_found_elem;
|
|
}
|
|
|
|
for (tp = timelib_timezone_lookup; tp->name; tp++) {
|
|
if (tp->full_tz_name && strcasecmp(word, tp->full_tz_name) == 0) {
|
|
if (!first_found) {
|
|
first_found = 1;
|
|
first_found_elem = tp;
|
|
if (gmtoffset == -1) {
|
|
return tp;
|
|
}
|
|
}
|
|
if (tp->gmtoffset == gmtoffset) {
|
|
return tp;
|
|
}
|
|
}
|
|
}
|
|
if (first_found) {
|
|
return first_found_elem;
|
|
}
|
|
|
|
|
|
/* Still didn't find anything, let's find the zone solely based on
|
|
* offset/isdst then */
|
|
for (fmp = timelib_timezone_fallbackmap; fmp->name; fmp++) {
|
|
if ((fmp->gmtoffset * 3600) == gmtoffset && fmp->type == isdst) {
|
|
return fmp;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static long timelib_lookup_zone(char **ptr, int *dst, char **tz_abbr, int *found)
|
|
{
|
|
char *word;
|
|
char *begin = *ptr, *end;
|
|
long value = 0;
|
|
const timelib_tz_lookup_table *tp;
|
|
|
|
while (**ptr != '\0' && **ptr != ')' && **ptr != ' ') {
|
|
++*ptr;
|
|
}
|
|
end = *ptr;
|
|
word = calloc(1, end - begin + 1);
|
|
memcpy(word, begin, end - begin);
|
|
|
|
if ((tp = zone_search(word, -1, 0))) {
|
|
value = -tp->gmtoffset / 60;
|
|
*dst = tp->type;
|
|
value += tp->type * 60;
|
|
*found = 1;
|
|
} else {
|
|
*found = 0;
|
|
}
|
|
|
|
*tz_abbr = word;
|
|
return value;
|
|
}
|
|
|
|
static long timelib_get_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;
|
|
long retval = 0;
|
|
|
|
*tz_not_found = 0;
|
|
|
|
while (**ptr == ' ' || **ptr == '\t' || **ptr == '(') {
|
|
++*ptr;
|
|
}
|
|
if ((*ptr)[0] == 'G' && (*ptr)[1] == 'M' && (*ptr)[2] == 'T' && ((*ptr)[3] == '+' || (*ptr)[3] == '-')) {
|
|
*ptr += 3;
|
|
}
|
|
if (**ptr == '+') {
|
|
++*ptr;
|
|
t->is_localtime = 1;
|
|
t->zone_type = TIMELIB_ZONETYPE_OFFSET;
|
|
*tz_not_found = 0;
|
|
t->dst = 0;
|
|
|
|
retval = -1 * timelib_parse_tz_cor(ptr);
|
|
} else if (**ptr == '-') {
|
|
++*ptr;
|
|
t->is_localtime = 1;
|
|
t->zone_type = TIMELIB_ZONETYPE_OFFSET;
|
|
*tz_not_found = 0;
|
|
t->dst = 0;
|
|
|
|
retval = timelib_parse_tz_cor(ptr);
|
|
} else {
|
|
int found = 0;
|
|
long offset;
|
|
char *tz_abbr;
|
|
|
|
t->is_localtime = 1;
|
|
|
|
offset = timelib_lookup_zone(ptr, dst, &tz_abbr, &found);
|
|
if (found) {
|
|
t->zone_type = TIMELIB_ZONETYPE_ABBR;
|
|
}
|
|
#if 0
|
|
/* If we found a TimeZone identifier, use it */
|
|
if (tz_name) {
|
|
t->tz_info = timelib_parse_tzfile(tz_name);
|
|
t->zone_type = TIMELIB_ZONETYPE_ID;
|
|
}
|
|
#endif
|
|
/* If we have a TimeZone identifier to start with, use it */
|
|
if (strstr(tz_abbr, "/") || strcmp(tz_abbr, "UTC") == 0) {
|
|
if ((res = tz_wrapper(tz_abbr, tzdb)) != NULL) {
|
|
t->tz_info = res;
|
|
t->zone_type = TIMELIB_ZONETYPE_ID;
|
|
found++;
|
|
}
|
|
}
|
|
if (found && t->zone_type != TIMELIB_ZONETYPE_ID) {
|
|
timelib_time_tz_abbr_update(t, tz_abbr);
|
|
}
|
|
free(tz_abbr);
|
|
*tz_not_found = (found == 0);
|
|
retval = offset;
|
|
}
|
|
while (**ptr == ')') {
|
|
++*ptr;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
#define timelib_split_free(arg) { \
|
|
int i; \
|
|
for (i = 0; i < arg.c; i++) { \
|
|
free(arg.v[i]); \
|
|
} \
|
|
if (arg.v) { \
|
|
free(arg.v); \
|
|
} \
|
|
}
|
|
|
|
static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
|
|
{
|
|
uchar *cursor = s->cur;
|
|
char *str, *ptr = NULL;
|
|
|
|
std:
|
|
s->tok = cursor;
|
|
s->len = 0;
|
|
/*!re2c
|
|
any = [\000-\377];
|
|
|
|
space = [ \t]+;
|
|
frac = "."[0-9]+;
|
|
|
|
ago = 'ago';
|
|
|
|
hour24 = [01]?[0-9] | "2"[0-4];
|
|
hour24lz = [01][0-9] | "2"[0-4];
|
|
hour12 = "0"?[1-9] | "1"[0-2];
|
|
minute = [0-5]?[0-9];
|
|
minutelz = [0-5][0-9];
|
|
second = minute | "60";
|
|
secondlz = minutelz | "60";
|
|
meridian = ([AaPp] "."? [Mm] "."?) [\000\t ];
|
|
tz = "("? [A-Za-z]{1,6} ")"? | [A-Z][a-z]+([_/-][A-Za-z]+)+;
|
|
tzcorrection = "GMT"? [+-] hour24 ":"? minute?;
|
|
|
|
daysuf = "st" | "nd" | "rd" | "th";
|
|
|
|
month = "0"? [0-9] | "1"[0-2];
|
|
day = (([0-2]?[0-9]) | ("3"[01])) daysuf?;
|
|
year = [0-9]{1,4};
|
|
year2 = [0-9]{2};
|
|
year4 = [0-9]{4};
|
|
year4withsign = [+-]? [0-9]{4};
|
|
|
|
dayofyear = "00"[1-9] | "0"[1-9][0-9] | [1-2][0-9][0-9] | "3"[0-5][0-9] | "36"[0-6];
|
|
weekofyear = "0"[1-9] | [1-4][0-9] | "5"[0-3];
|
|
|
|
monthlz = "0" [0-9] | "1" [0-2];
|
|
daylz = "0" [0-9] | [1-2][0-9] | "3" [01];
|
|
|
|
dayfull = 'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday';
|
|
dayabbr = 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat' | 'sun';
|
|
dayspecial = 'weekday' | 'weekdays';
|
|
daytext = dayfull | dayabbr | dayspecial;
|
|
|
|
monthfull = 'january' | 'february' | 'march' | 'april' | 'may' | 'june' | 'july' | 'august' | 'september' | 'october' | 'november' | 'december';
|
|
monthabbr = 'jan' | 'feb' | 'mar' | 'apr' | 'may' | 'jun' | 'jul' | 'aug' | 'sep' | 'sept' | 'oct' | 'nov' | 'dec';
|
|
monthroman = "I" | "II" | "III" | "IV" | "V" | "VI" | "VII" | "VIII" | "IX" | "X" | "XI" | "XII";
|
|
monthtext = monthfull | monthabbr | monthroman;
|
|
|
|
/* Time formats */
|
|
timetiny12 = hour12 space? meridian;
|
|
timeshort12 = hour12[:.]minutelz space? meridian;
|
|
timelong12 = hour12[:.]minute[:.]secondlz space? meridian;
|
|
|
|
timeshort24 = 't'? hour24[:.]minute;
|
|
timelong24 = 't'? hour24[:.]minute[:.]second;
|
|
iso8601long = 't'? hour24 [:.] minute [:.] second frac;
|
|
|
|
/* iso8601shorttz = hour24 [:] minutelz space? (tzcorrection | tz); */
|
|
iso8601normtz = 't'? hour24 [:.] minute [:.] secondlz space? (tzcorrection | tz);
|
|
/* iso8601longtz = hour24 [:] minute [:] secondlz frac space? (tzcorrection | tz); */
|
|
|
|
gnunocolon = 't'? hour24lz minutelz;
|
|
/* gnunocolontz = hour24lz minutelz space? (tzcorrection | tz); */
|
|
iso8601nocolon = 't'? hour24lz minutelz secondlz;
|
|
/* iso8601nocolontz = hour24lz minutelz secondlz space? (tzcorrection | tz); */
|
|
|
|
/* Date formats */
|
|
americanshort = month "/" day;
|
|
american = month "/" day "/" year;
|
|
iso8601dateslash = year4 "/" monthlz "/" daylz "/"?;
|
|
dateslash = year4 "/" month "/" day;
|
|
iso8601date4 = year4withsign "-" monthlz "-" daylz;
|
|
iso8601date2 = year2 "-" monthlz "-" daylz;
|
|
gnudateshorter = year4 "-" month;
|
|
gnudateshort = year "-" month "-" day;
|
|
pointeddate4 = day [.\t-] month [.-] year4;
|
|
pointeddate2 = day [.\t] month "." year2;
|
|
datefull = day ([ \t.-])* monthtext ([ \t.-])* year;
|
|
datenoday = monthtext ([ .\t-])* year4;
|
|
datenodayrev = year4 ([ .\t-])* monthtext;
|
|
datetextual = monthtext ([ .\t-])* day [,.stndrh\t ]+ year;
|
|
datenoyear = monthtext ([ .\t-])* day [,.stndrh\t ]*;
|
|
datenoyearrev = day ([ .\t-])* monthtext;
|
|
datenocolon = year4 monthlz daylz;
|
|
|
|
/* Special formats */
|
|
soap = year4 "-" monthlz "-" daylz "T" hour24lz ":" minutelz ":" secondlz frac tzcorrection?;
|
|
xmlrpc = year4 monthlz daylz "T" hour24 ":" minutelz ":" secondlz;
|
|
xmlrpcnocolon = year4 monthlz daylz 't' hour24 minutelz secondlz;
|
|
wddx = year4 "-" month "-" day "T" hour24 ":" minute ":" second;
|
|
pgydotd = year4 "."? dayofyear;
|
|
pgtextshort = monthabbr "-" daylz "-" year;
|
|
pgtextreverse = year "-" monthabbr "-" daylz;
|
|
mssqltime = hour12 ":" minutelz ":" secondlz [:.] [0-9]+ meridian;
|
|
isoweekday = year4 "-"? "W" weekofyear "-"? [0-7];
|
|
isoweek = year4 "-"? "W" weekofyear;
|
|
exif = year4 ":" monthlz ":" daylz " " hour24lz ":" minutelz ":" secondlz;
|
|
firstdayof = 'first day of'?;
|
|
lastdayof = 'last day of'?;
|
|
backof = 'back of ' hour24 space? meridian?;
|
|
frontof = 'front of ' hour24 space? meridian?;
|
|
|
|
/* Common Log Format: 10/Oct/2000:13:55:36 -0700 */
|
|
clf = day "/" monthabbr "/" year4 ":" hour24lz ":" minutelz ":" secondlz space tzcorrection;
|
|
|
|
/* Timestamp format: @1126396800 */
|
|
timestamp = "@" "-"? [0-9]+;
|
|
|
|
/* To fix some ambiguities */
|
|
dateshortwithtimeshort12 = datenoyear timeshort12;
|
|
dateshortwithtimelong12 = datenoyear timelong12;
|
|
dateshortwithtimeshort = datenoyear timeshort24;
|
|
dateshortwithtimelong = datenoyear timelong24;
|
|
dateshortwithtimelongtz = datenoyear iso8601normtz;
|
|
|
|
/*
|
|
* Relative regexps
|
|
*/
|
|
reltextnumber = 'first'|'second'|'third'|'fourth'|'fifth'|'sixth'|'seventh'|'eight'|'eighth'|'ninth'|'tenth'|'eleventh'|'twelfth';
|
|
reltexttext = 'next'|'last'|'previous'|'this';
|
|
reltextunit = (('sec'|'second'|'min'|'minute'|'hour'|'day'|'fortnight'|'forthnight'|'month'|'year') 's'?) | 'weeks' | daytext;
|
|
|
|
relnumber = ([+-]*[ \t]*[0-9]+);
|
|
relative = relnumber space? (reltextunit | 'week' );
|
|
relativetext = (reltextnumber|reltexttext) space reltextunit;
|
|
relativetextweek = reltexttext space 'week';
|
|
|
|
weekdayof = (reltextnumber|reltexttext) space (dayfull|dayabbr) space 'of';
|
|
|
|
*/
|
|
|
|
/*!re2c
|
|
/* so that vim highlights correctly */
|
|
'yesterday'
|
|
{
|
|
DEBUG_OUTPUT("yesterday");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_RELATIVE();
|
|
TIMELIB_UNHAVE_TIME();
|
|
|
|
s->time->relative.d = -1;
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_RELATIVE;
|
|
}
|
|
|
|
'now'
|
|
{
|
|
DEBUG_OUTPUT("now");
|
|
TIMELIB_INIT;
|
|
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_RELATIVE;
|
|
}
|
|
|
|
'noon'
|
|
{
|
|
DEBUG_OUTPUT("noon");
|
|
TIMELIB_INIT;
|
|
TIMELIB_UNHAVE_TIME();
|
|
TIMELIB_HAVE_TIME();
|
|
s->time->h = 12;
|
|
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_RELATIVE;
|
|
}
|
|
|
|
'midnight' | 'today'
|
|
{
|
|
DEBUG_OUTPUT("midnight | today");
|
|
TIMELIB_INIT;
|
|
TIMELIB_UNHAVE_TIME();
|
|
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_RELATIVE;
|
|
}
|
|
|
|
'tomorrow'
|
|
{
|
|
DEBUG_OUTPUT("tomorrow");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_RELATIVE();
|
|
TIMELIB_UNHAVE_TIME();
|
|
|
|
s->time->relative.d = 1;
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_RELATIVE;
|
|
}
|
|
|
|
timestamp
|
|
{
|
|
timelib_ull i;
|
|
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_RELATIVE();
|
|
TIMELIB_UNHAVE_DATE();
|
|
TIMELIB_UNHAVE_TIME();
|
|
TIMELIB_HAVE_TZ();
|
|
|
|
i = timelib_get_unsigned_nr((char **) &ptr, 24);
|
|
s->time->y = 1970;
|
|
s->time->m = 1;
|
|
s->time->d = 1;
|
|
s->time->h = s->time->i = s->time->s = 0;
|
|
s->time->f = 0.0;
|
|
s->time->relative.s += i;
|
|
s->time->is_localtime = 1;
|
|
s->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
|
|
s->time->z = 0;
|
|
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_RELATIVE;
|
|
}
|
|
|
|
firstdayof | lastdayof
|
|
{
|
|
DEBUG_OUTPUT("firstdayof | lastdayof");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_RELATIVE();
|
|
|
|
/* skip "last day of" or "first day of" */
|
|
if (*ptr == 'l') {
|
|
s->time->relative.first_last_day_of = 2;
|
|
} else {
|
|
s->time->relative.first_last_day_of = 1;
|
|
}
|
|
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_LF_DAY_OF_MONTH;
|
|
}
|
|
|
|
backof | frontof
|
|
{
|
|
DEBUG_OUTPUT("backof | frontof");
|
|
TIMELIB_INIT;
|
|
TIMELIB_UNHAVE_TIME();
|
|
TIMELIB_HAVE_TIME();
|
|
|
|
if (*ptr == 'b') {
|
|
s->time->h = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->i = 15;
|
|
} else {
|
|
s->time->h = timelib_get_nr((char **) &ptr, 2) - 1;
|
|
s->time->i = 45;
|
|
}
|
|
if (*ptr != '\0' ) {
|
|
timelib_eat_spaces((char **) &ptr);
|
|
s->time->h += timelib_meridian((char **) &ptr, s->time->h);
|
|
}
|
|
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_LF_DAY_OF_MONTH;
|
|
}
|
|
|
|
weekdayof
|
|
{
|
|
timelib_sll i;
|
|
int behavior = 0;
|
|
DEBUG_OUTPUT("weekdayof");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_RELATIVE();
|
|
TIMELIB_HAVE_SPECIAL_RELATIVE();
|
|
|
|
i = timelib_get_relative_text((char **) &ptr, &behavior);
|
|
timelib_eat_spaces((char **) &ptr);
|
|
if (i > 0) { /* first, second... etc */
|
|
s->time->relative.special.type = TIMELIB_SPECIAL_DAY_OF_WEEK_IN_MONTH;
|
|
timelib_set_relative((char **) &ptr, i, 1, s);
|
|
} else { /* last */
|
|
s->time->relative.special.type = TIMELIB_SPECIAL_LAST_DAY_OF_WEEK_IN_MONTH;
|
|
timelib_set_relative((char **) &ptr, i, behavior, s);
|
|
}
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_WEEK_DAY_OF_MONTH;
|
|
}
|
|
|
|
timetiny12 | timeshort12 | timelong12
|
|
{
|
|
DEBUG_OUTPUT("timetiny12 | timeshort12 | timelong12");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_TIME();
|
|
s->time->h = timelib_get_nr((char **) &ptr, 2);
|
|
if (*ptr == ':' || *ptr == '.') {
|
|
s->time->i = timelib_get_nr((char **) &ptr, 2);
|
|
if (*ptr == ':' || *ptr == '.') {
|
|
s->time->s = timelib_get_nr((char **) &ptr, 2);
|
|
}
|
|
}
|
|
s->time->h += timelib_meridian((char **) &ptr, s->time->h);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_TIME12;
|
|
}
|
|
|
|
mssqltime
|
|
{
|
|
DEBUG_OUTPUT("mssqltime");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_TIME();
|
|
s->time->h = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->i = timelib_get_nr((char **) &ptr, 2);
|
|
if (*ptr == ':' || *ptr == '.') {
|
|
s->time->s = timelib_get_nr((char **) &ptr, 2);
|
|
|
|
if (*ptr == ':' || *ptr == '.') {
|
|
s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
|
|
}
|
|
}
|
|
timelib_eat_spaces((char **) &ptr);
|
|
s->time->h += timelib_meridian((char **) &ptr, s->time->h);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_TIME24_WITH_ZONE;
|
|
}
|
|
|
|
timeshort24 | timelong24 /* | iso8601short | iso8601norm */ | iso8601long /*| iso8601shorttz | iso8601normtz | iso8601longtz*/
|
|
{
|
|
int tz_not_found;
|
|
DEBUG_OUTPUT("timeshort24 | timelong24 | iso8601long");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_TIME();
|
|
s->time->h = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->i = timelib_get_nr((char **) &ptr, 2);
|
|
if (*ptr == ':' || *ptr == '.') {
|
|
s->time->s = timelib_get_nr((char **) &ptr, 2);
|
|
|
|
if (*ptr == '.') {
|
|
s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
|
|
}
|
|
}
|
|
|
|
if (*ptr != '\0') {
|
|
s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
|
|
if (tz_not_found) {
|
|
add_error(s, "The timezone could not be found in the database");
|
|
}
|
|
}
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_TIME24_WITH_ZONE;
|
|
}
|
|
|
|
gnunocolon
|
|
{
|
|
DEBUG_OUTPUT("gnunocolon");
|
|
TIMELIB_INIT;
|
|
switch (s->time->have_time) {
|
|
case 0:
|
|
s->time->h = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->i = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->s = 0;
|
|
break;
|
|
case 1:
|
|
s->time->y = timelib_get_nr((char **) &ptr, 4);
|
|
break;
|
|
default:
|
|
TIMELIB_DEINIT;
|
|
add_error(s, "Double time specification");
|
|
return TIMELIB_ERROR;
|
|
}
|
|
s->time->have_time++;
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_GNU_NOCOLON;
|
|
}
|
|
/*
|
|
gnunocolontz
|
|
{
|
|
DEBUG_OUTPUT("gnunocolontz");
|
|
TIMELIB_INIT;
|
|
switch (s->time->have_time) {
|
|
case 0:
|
|
s->time->h = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->i = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->s = 0;
|
|
s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, s->tzdb, tz_get_wrapper);
|
|
break;
|
|
case 1:
|
|
s->time->y = timelib_get_nr((char **) &ptr, 4);
|
|
break;
|
|
default:
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_ERROR;
|
|
}
|
|
s->time->have_time++;
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_GNU_NOCOLON_TZ;
|
|
}
|
|
*/
|
|
iso8601nocolon /*| iso8601nocolontz*/
|
|
{
|
|
int tz_not_found;
|
|
DEBUG_OUTPUT("iso8601nocolon");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_TIME();
|
|
s->time->h = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->i = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->s = timelib_get_nr((char **) &ptr, 2);
|
|
|
|
if (*ptr != '\0') {
|
|
s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
|
|
if (tz_not_found) {
|
|
add_error(s, "The timezone could not be found in the database");
|
|
}
|
|
}
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_ISO_NOCOLON;
|
|
}
|
|
|
|
americanshort | american
|
|
{
|
|
int length = 0;
|
|
DEBUG_OUTPUT("americanshort | american");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->m = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->d = timelib_get_nr((char **) &ptr, 2);
|
|
if (*ptr == '/') {
|
|
s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
|
|
TIMELIB_PROCESS_YEAR(s->time->y, length);
|
|
}
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_AMERICAN;
|
|
}
|
|
|
|
iso8601date4 | iso8601dateslash | dateslash
|
|
{
|
|
DEBUG_OUTPUT("iso8601date4 | iso8601date2 | iso8601dateslash | dateslash");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->y = timelib_get_unsigned_nr((char **) &ptr, 4);
|
|
s->time->m = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->d = timelib_get_nr((char **) &ptr, 2);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_ISO_DATE;
|
|
}
|
|
|
|
iso8601date2
|
|
{
|
|
int length = 0;
|
|
DEBUG_OUTPUT("iso8601date2");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
|
|
s->time->m = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->d = timelib_get_nr((char **) &ptr, 2);
|
|
TIMELIB_PROCESS_YEAR(s->time->y, length);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_ISO_DATE;
|
|
}
|
|
|
|
gnudateshorter
|
|
{
|
|
int length = 0;
|
|
DEBUG_OUTPUT("gnudateshorter");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
|
|
s->time->m = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->d = 1;
|
|
TIMELIB_PROCESS_YEAR(s->time->y, length);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_ISO_DATE;
|
|
}
|
|
|
|
gnudateshort
|
|
{
|
|
int length = 0;
|
|
DEBUG_OUTPUT("gnudateshort");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
|
|
s->time->m = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->d = timelib_get_nr((char **) &ptr, 2);
|
|
TIMELIB_PROCESS_YEAR(s->time->y, length);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_ISO_DATE;
|
|
}
|
|
|
|
datefull
|
|
{
|
|
int length = 0;
|
|
DEBUG_OUTPUT("datefull");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->d = timelib_get_nr((char **) &ptr, 2);
|
|
timelib_skip_day_suffix((char **) &ptr);
|
|
s->time->m = timelib_get_month((char **) &ptr);
|
|
s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
|
|
TIMELIB_PROCESS_YEAR(s->time->y, length);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_DATE_FULL;
|
|
}
|
|
|
|
pointeddate4
|
|
{
|
|
DEBUG_OUTPUT("pointed date YYYY");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->d = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->m = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->y = timelib_get_nr((char **) &ptr, 4);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_DATE_FULL_POINTED;
|
|
}
|
|
|
|
pointeddate2
|
|
{
|
|
int length = 0;
|
|
DEBUG_OUTPUT("pointed date YY");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->d = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->m = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length);
|
|
TIMELIB_PROCESS_YEAR(s->time->y, length);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_DATE_FULL_POINTED;
|
|
}
|
|
|
|
datenoday
|
|
{
|
|
int length = 0;
|
|
DEBUG_OUTPUT("datenoday");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->m = timelib_get_month((char **) &ptr);
|
|
s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
|
|
s->time->d = 1;
|
|
TIMELIB_PROCESS_YEAR(s->time->y, length);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_DATE_NO_DAY;
|
|
}
|
|
|
|
datenodayrev
|
|
{
|
|
int length = 0;
|
|
DEBUG_OUTPUT("datenodayrev");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
|
|
s->time->m = timelib_get_month((char **) &ptr);
|
|
s->time->d = 1;
|
|
TIMELIB_PROCESS_YEAR(s->time->y, length);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_DATE_NO_DAY;
|
|
}
|
|
|
|
datetextual | datenoyear
|
|
{
|
|
int length = 0;
|
|
DEBUG_OUTPUT("datetextual | datenoyear");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->m = timelib_get_month((char **) &ptr);
|
|
s->time->d = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
|
|
TIMELIB_PROCESS_YEAR(s->time->y, length);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_DATE_TEXT;
|
|
}
|
|
|
|
datenoyearrev
|
|
{
|
|
DEBUG_OUTPUT("datenoyearrev");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->d = timelib_get_nr((char **) &ptr, 2);
|
|
timelib_skip_day_suffix((char **) &ptr);
|
|
s->time->m = timelib_get_month((char **) &ptr);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_DATE_TEXT;
|
|
}
|
|
|
|
datenocolon
|
|
{
|
|
DEBUG_OUTPUT("datenocolon");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->y = timelib_get_nr((char **) &ptr, 4);
|
|
s->time->m = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->d = timelib_get_nr((char **) &ptr, 2);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_DATE_NOCOLON;
|
|
}
|
|
|
|
xmlrpc | xmlrpcnocolon | soap | wddx | exif
|
|
{
|
|
int tz_not_found;
|
|
DEBUG_OUTPUT("xmlrpc | xmlrpcnocolon | soap | wddx | exif");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_TIME();
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->y = timelib_get_nr((char **) &ptr, 4);
|
|
s->time->m = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->d = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->h = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->i = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->s = timelib_get_nr((char **) &ptr, 2);
|
|
if (*ptr == '.') {
|
|
s->time->f = timelib_get_frac_nr((char **) &ptr, 9);
|
|
if (*ptr) { /* timezone is optional */
|
|
s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
|
|
if (tz_not_found) {
|
|
add_error(s, "The timezone could not be found in the database");
|
|
}
|
|
}
|
|
}
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_XMLRPC_SOAP;
|
|
}
|
|
|
|
pgydotd
|
|
{
|
|
int length = 0;
|
|
DEBUG_OUTPUT("pgydotd");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
|
|
s->time->d = timelib_get_nr((char **) &ptr, 3);
|
|
s->time->m = 1;
|
|
TIMELIB_PROCESS_YEAR(s->time->y, length);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_PG_YEARDAY;
|
|
}
|
|
|
|
isoweekday
|
|
{
|
|
timelib_sll w, d;
|
|
DEBUG_OUTPUT("isoweekday");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
TIMELIB_HAVE_RELATIVE();
|
|
|
|
s->time->y = timelib_get_nr((char **) &ptr, 4);
|
|
w = timelib_get_nr((char **) &ptr, 2);
|
|
d = timelib_get_nr((char **) &ptr, 1);
|
|
s->time->m = 1;
|
|
s->time->d = 1;
|
|
s->time->relative.d = timelib_daynr_from_weeknr(s->time->y, w, d);
|
|
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_ISO_WEEK;
|
|
}
|
|
|
|
isoweek
|
|
{
|
|
timelib_sll w, d;
|
|
DEBUG_OUTPUT("isoweek");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
TIMELIB_HAVE_RELATIVE();
|
|
|
|
s->time->y = timelib_get_nr((char **) &ptr, 4);
|
|
w = timelib_get_nr((char **) &ptr, 2);
|
|
d = 1;
|
|
s->time->m = 1;
|
|
s->time->d = 1;
|
|
s->time->relative.d = timelib_daynr_from_weeknr(s->time->y, w, d);
|
|
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_ISO_WEEK;
|
|
}
|
|
|
|
pgtextshort
|
|
{
|
|
int length = 0;
|
|
DEBUG_OUTPUT("pgtextshort");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->m = timelib_get_month((char **) &ptr);
|
|
s->time->d = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
|
|
TIMELIB_PROCESS_YEAR(s->time->y, length);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_PG_TEXT;
|
|
}
|
|
|
|
pgtextreverse
|
|
{
|
|
int length = 0;
|
|
DEBUG_OUTPUT("pgtextreverse");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
|
|
s->time->m = timelib_get_month((char **) &ptr);
|
|
s->time->d = timelib_get_nr((char **) &ptr, 2);
|
|
TIMELIB_PROCESS_YEAR(s->time->y, length);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_PG_TEXT;
|
|
}
|
|
|
|
clf
|
|
{
|
|
int tz_not_found;
|
|
DEBUG_OUTPUT("clf");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_TIME();
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->d = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->m = timelib_get_month((char **) &ptr);
|
|
s->time->y = timelib_get_nr((char **) &ptr, 4);
|
|
s->time->h = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->i = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->s = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
|
|
if (tz_not_found) {
|
|
add_error(s, "The timezone could not be found in the database");
|
|
}
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_CLF;
|
|
}
|
|
|
|
year4
|
|
{
|
|
DEBUG_OUTPUT("year4");
|
|
TIMELIB_INIT;
|
|
s->time->y = timelib_get_nr((char **) &ptr, 4);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_CLF;
|
|
}
|
|
|
|
ago
|
|
{
|
|
DEBUG_OUTPUT("ago");
|
|
TIMELIB_INIT;
|
|
s->time->relative.y = 0 - s->time->relative.y;
|
|
s->time->relative.m = 0 - s->time->relative.m;
|
|
s->time->relative.d = 0 - s->time->relative.d;
|
|
s->time->relative.h = 0 - s->time->relative.h;
|
|
s->time->relative.i = 0 - s->time->relative.i;
|
|
s->time->relative.s = 0 - s->time->relative.s;
|
|
s->time->relative.weekday = 0 - s->time->relative.weekday;
|
|
if (s->time->relative.weekday == 0) {
|
|
s->time->relative.weekday = -7;
|
|
}
|
|
if (s->time->relative.have_special_relative && s->time->relative.special.type == TIMELIB_SPECIAL_WEEKDAY) {
|
|
s->time->relative.special.amount = 0 - s->time->relative.special.amount;
|
|
}
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_AGO;
|
|
}
|
|
|
|
daytext
|
|
{
|
|
const timelib_relunit* relunit;
|
|
DEBUG_OUTPUT("daytext");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_RELATIVE();
|
|
TIMELIB_HAVE_WEEKDAY_RELATIVE();
|
|
TIMELIB_UNHAVE_TIME();
|
|
relunit = timelib_lookup_relunit((char**) &ptr);
|
|
s->time->relative.weekday = relunit->multiplier;
|
|
if (s->time->relative.weekday_behavior != 2) {
|
|
s->time->relative.weekday_behavior = 1;
|
|
}
|
|
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_WEEKDAY;
|
|
}
|
|
|
|
relativetextweek
|
|
{
|
|
timelib_sll i;
|
|
int behavior = 0;
|
|
DEBUG_OUTPUT("relativetextweek");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_RELATIVE();
|
|
|
|
while(*ptr) {
|
|
i = timelib_get_relative_text((char **) &ptr, &behavior);
|
|
timelib_eat_spaces((char **) &ptr);
|
|
timelib_set_relative((char **) &ptr, i, behavior, s);
|
|
s->time->relative.weekday_behavior = 2;
|
|
|
|
/* to handle the format weekday + last/this/next week */
|
|
if (s->time->relative.have_weekday_relative == 0) {
|
|
TIMELIB_HAVE_WEEKDAY_RELATIVE();
|
|
s->time->relative.weekday = 1;
|
|
}
|
|
}
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_RELATIVE;
|
|
}
|
|
|
|
relativetext
|
|
{
|
|
timelib_sll i;
|
|
int behavior = 0;
|
|
DEBUG_OUTPUT("relativetext");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_RELATIVE();
|
|
|
|
while(*ptr) {
|
|
i = timelib_get_relative_text((char **) &ptr, &behavior);
|
|
timelib_eat_spaces((char **) &ptr);
|
|
timelib_set_relative((char **) &ptr, i, behavior, s);
|
|
}
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_RELATIVE;
|
|
}
|
|
|
|
monthfull | monthabbr
|
|
{
|
|
DEBUG_OUTPUT("monthtext");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->m = timelib_lookup_month((char **) &ptr);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_DATE_TEXT;
|
|
}
|
|
|
|
tzcorrection | tz
|
|
{
|
|
int tz_not_found;
|
|
DEBUG_OUTPUT("tzcorrection | tz");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_TZ();
|
|
s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
|
|
if (tz_not_found) {
|
|
add_error(s, "The timezone could not be found in the database");
|
|
}
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_TIMEZONE;
|
|
}
|
|
|
|
dateshortwithtimeshort12 | dateshortwithtimelong12
|
|
{
|
|
DEBUG_OUTPUT("dateshortwithtimeshort12 | dateshortwithtimelong12");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->m = timelib_get_month((char **) &ptr);
|
|
s->time->d = timelib_get_nr((char **) &ptr, 2);
|
|
|
|
TIMELIB_HAVE_TIME();
|
|
s->time->h = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->i = timelib_get_nr((char **) &ptr, 2);
|
|
if (*ptr == ':' || *ptr == '.') {
|
|
s->time->s = timelib_get_nr((char **) &ptr, 2);
|
|
|
|
if (*ptr == '.') {
|
|
s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
|
|
}
|
|
}
|
|
|
|
s->time->h += timelib_meridian((char **) &ptr, s->time->h);
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_SHORTDATE_WITH_TIME;
|
|
}
|
|
|
|
dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz
|
|
{
|
|
int tz_not_found;
|
|
DEBUG_OUTPUT("dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_DATE();
|
|
s->time->m = timelib_get_month((char **) &ptr);
|
|
s->time->d = timelib_get_nr((char **) &ptr, 2);
|
|
|
|
TIMELIB_HAVE_TIME();
|
|
s->time->h = timelib_get_nr((char **) &ptr, 2);
|
|
s->time->i = timelib_get_nr((char **) &ptr, 2);
|
|
if (*ptr == ':') {
|
|
s->time->s = timelib_get_nr((char **) &ptr, 2);
|
|
|
|
if (*ptr == '.') {
|
|
s->time->f = timelib_get_frac_nr((char **) &ptr, 8);
|
|
}
|
|
}
|
|
|
|
if (*ptr != '\0') {
|
|
s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
|
|
if (tz_not_found) {
|
|
add_error(s, "The timezone could not be found in the database");
|
|
}
|
|
}
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_SHORTDATE_WITH_TIME;
|
|
}
|
|
|
|
relative
|
|
{
|
|
timelib_ull i;
|
|
DEBUG_OUTPUT("relative");
|
|
TIMELIB_INIT;
|
|
TIMELIB_HAVE_RELATIVE();
|
|
|
|
while(*ptr) {
|
|
i = timelib_get_unsigned_nr((char **) &ptr, 24);
|
|
timelib_eat_spaces((char **) &ptr);
|
|
timelib_set_relative((char **) &ptr, i, 1, s);
|
|
}
|
|
TIMELIB_DEINIT;
|
|
return TIMELIB_RELATIVE;
|
|
}
|
|
|
|
[ .,\t]
|
|
{
|
|
goto std;
|
|
}
|
|
|
|
"\000"|"\n"
|
|
{
|
|
s->pos = cursor; s->line++;
|
|
goto std;
|
|
}
|
|
|
|
any
|
|
{
|
|
add_error(s, "Unexpected character");
|
|
goto std;
|
|
}
|
|
*/
|
|
}
|
|
|
|
/*!max:re2c */
|
|
|
|
timelib_time* timelib_strtotime(char *s, int len, struct timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper)
|
|
{
|
|
Scanner in;
|
|
int t;
|
|
char *e = s + len - 1;
|
|
|
|
memset(&in, 0, sizeof(in));
|
|
in.errors = malloc(sizeof(struct timelib_error_container));
|
|
in.errors->warning_count = 0;
|
|
in.errors->warning_messages = NULL;
|
|
in.errors->error_count = 0;
|
|
in.errors->error_messages = NULL;
|
|
|
|
if (len > 0) {
|
|
while (isspace(*s) && s < e) {
|
|
s++;
|
|
}
|
|
while (isspace(*e) && e > s) {
|
|
e--;
|
|
}
|
|
}
|
|
if (e - s < 0) {
|
|
in.time = timelib_time_ctor();
|
|
add_error(&in, "Empty string");
|
|
if (errors) {
|
|
*errors = in.errors;
|
|
} else {
|
|
timelib_error_container_dtor(in.errors);
|
|
}
|
|
in.time->y = in.time->d = in.time->m = in.time->h = in.time->i = in.time->s = in.time->f = in.time->dst = in.time->z = TIMELIB_UNSET;
|
|
in.time->is_localtime = in.time->zone_type = 0;
|
|
return in.time;
|
|
}
|
|
e++;
|
|
|
|
in.str = malloc((e - s) + YYMAXFILL);
|
|
memset(in.str, 0, (e - s) + YYMAXFILL);
|
|
memcpy(in.str, s, (e - s));
|
|
in.lim = in.str + (e - s) + YYMAXFILL;
|
|
in.cur = in.str;
|
|
in.time = timelib_time_ctor();
|
|
in.time->y = TIMELIB_UNSET;
|
|
in.time->d = TIMELIB_UNSET;
|
|
in.time->m = TIMELIB_UNSET;
|
|
in.time->h = TIMELIB_UNSET;
|
|
in.time->i = TIMELIB_UNSET;
|
|
in.time->s = TIMELIB_UNSET;
|
|
in.time->f = TIMELIB_UNSET;
|
|
in.time->z = TIMELIB_UNSET;
|
|
in.time->dst = TIMELIB_UNSET;
|
|
in.tzdb = tzdb;
|
|
in.time->is_localtime = 0;
|
|
in.time->zone_type = 0;
|
|
|
|
do {
|
|
t = scan(&in, tz_get_wrapper);
|
|
#ifdef DEBUG_PARSER
|
|
printf("%d\n", t);
|
|
#endif
|
|
} while(t != EOI);
|
|
|
|
/* do funky checking whether the parsed time was valid time */
|
|
if (in.time->have_time && !timelib_valid_time( in.time->h, in.time->i, in.time->s)) {
|
|
add_warning(&in, "The parsed time was invalid");
|
|
}
|
|
/* do funky checking whether the parsed date was valid date */
|
|
if (in.time->have_date && !timelib_valid_date( in.time->y, in.time->m, in.time->d)) {
|
|
add_warning(&in, "The parsed date was invalid");
|
|
}
|
|
|
|
free(in.str);
|
|
if (errors) {
|
|
*errors = in.errors;
|
|
} else {
|
|
timelib_error_container_dtor(in.errors);
|
|
}
|
|
return in.time;
|
|
}
|
|
|
|
#define TIMELIB_CHECK_NUMBER \
|
|
if (strchr("0123456789", *ptr) == NULL) \
|
|
{ \
|
|
add_pbf_error(s, "Unexpected data found.", string, begin); \
|
|
}
|
|
|
|
static void timelib_time_reset_fields(timelib_time *time)
|
|
{
|
|
assert(time != NULL);
|
|
|
|
time->y = 1970;
|
|
time->m = 1;
|
|
time->d = 1;
|
|
time->h = time->i = time->s = 0;
|
|
time->f = 0.0;
|
|
time->tz_info = NULL;
|
|
}
|
|
|
|
static void timelib_time_reset_unset_fields(timelib_time *time)
|
|
{
|
|
assert(time != NULL);
|
|
|
|
if (time->y == TIMELIB_UNSET ) time->y = 1970;
|
|
if (time->m == TIMELIB_UNSET ) time->m = 1;
|
|
if (time->d == TIMELIB_UNSET ) time->d = 1;
|
|
if (time->h == TIMELIB_UNSET ) time->h = 0;
|
|
if (time->i == TIMELIB_UNSET ) time->i = 0;
|
|
if (time->s == TIMELIB_UNSET ) time->s = 0;
|
|
if (time->f == TIMELIB_UNSET ) time->f = 0.0;
|
|
}
|
|
|
|
timelib_time *timelib_parse_from_format(char *format, char *string, int 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;
|
|
|
|
memset(&in, 0, sizeof(in));
|
|
in.errors = malloc(sizeof(struct timelib_error_container));
|
|
in.errors->warning_count = 0;
|
|
in.errors->warning_messages = NULL;
|
|
in.errors->error_count = 0;
|
|
in.errors->error_messages = NULL;
|
|
|
|
in.time = timelib_time_ctor();
|
|
in.time->y = TIMELIB_UNSET;
|
|
in.time->d = TIMELIB_UNSET;
|
|
in.time->m = TIMELIB_UNSET;
|
|
in.time->h = TIMELIB_UNSET;
|
|
in.time->i = TIMELIB_UNSET;
|
|
in.time->s = TIMELIB_UNSET;
|
|
in.time->f = TIMELIB_UNSET;
|
|
in.time->z = TIMELIB_UNSET;
|
|
in.time->dst = TIMELIB_UNSET;
|
|
in.tzdb = tzdb;
|
|
in.time->is_localtime = 0;
|
|
in.time->zone_type = 0;
|
|
|
|
/* Loop over the format string */
|
|
while (*fptr && *ptr) {
|
|
begin = ptr;
|
|
switch (*fptr) {
|
|
case 'D': /* three letter day */
|
|
case 'l': /* full day */
|
|
{
|
|
const timelib_relunit* tmprel = 0;
|
|
|
|
tmprel = timelib_lookup_relunit((char **) &ptr);
|
|
if (!tmprel) {
|
|
add_pbf_error(s, "A textual day could not be found", string, begin);
|
|
break;
|
|
} else {
|
|
in.time->have_relative = 1;
|
|
in.time->relative.have_weekday_relative = 1;
|
|
in.time->relative.weekday = tmprel->multiplier;
|
|
in.time->relative.weekday_behavior = 1;
|
|
}
|
|
}
|
|
break;
|
|
case 'd': /* two digit day, with leading zero */
|
|
case 'j': /* two digit day, without leading zero */
|
|
TIMELIB_CHECK_NUMBER;
|
|
if ((s->time->d = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
|
|
add_pbf_error(s, "A two digit day could not be found", string, begin);
|
|
}
|
|
break;
|
|
case 'S': /* 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 */
|
|
TIMELIB_CHECK_NUMBER;
|
|
if ((tmp = timelib_get_nr((char **) &ptr, 3)) == TIMELIB_UNSET) {
|
|
add_pbf_error(s, "A three digit day-of-year could not be found", string, begin);
|
|
} else {
|
|
s->time->m = 1;
|
|
s->time->d = tmp + 1;
|
|
timelib_do_normalize(s->time);
|
|
}
|
|
break;
|
|
|
|
case 'm': /* two digit month, with leading zero */
|
|
case 'n': /* two digit month, without leading zero */
|
|
TIMELIB_CHECK_NUMBER;
|
|
if ((s->time->m = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
|
|
add_pbf_error(s, "A two digit month could not be found", string, begin);
|
|
}
|
|
break;
|
|
case 'M': /* three letter month */
|
|
case 'F': /* full month */
|
|
tmp = timelib_lookup_month((char **) &ptr);
|
|
if (!tmp) {
|
|
add_pbf_error(s, "A textual month could not be found", string, begin);
|
|
} else {
|
|
s->time->m = tmp;
|
|
}
|
|
break;
|
|
case 'y': /* two digit year */
|
|
{
|
|
int length = 0;
|
|
TIMELIB_CHECK_NUMBER;
|
|
if ((s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length)) == TIMELIB_UNSET) {
|
|
add_pbf_error(s, "A two digit year could not be found", string, begin);
|
|
}
|
|
TIMELIB_PROCESS_YEAR(s->time->y, length);
|
|
}
|
|
break;
|
|
case 'Y': /* four digit year */
|
|
TIMELIB_CHECK_NUMBER;
|
|
if ((s->time->y = timelib_get_nr((char **) &ptr, 4)) == TIMELIB_UNSET) {
|
|
add_pbf_error(s, "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 */
|
|
TIMELIB_CHECK_NUMBER;
|
|
if ((s->time->h = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
|
|
add_pbf_error(s, "A two digit hour could not be found", string, begin);
|
|
}
|
|
if (s->time->h > 12) {
|
|
add_pbf_error(s, "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 */
|
|
TIMELIB_CHECK_NUMBER;
|
|
if ((s->time->h = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
|
|
add_pbf_error(s, "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. */
|
|
if (s->time->h == TIMELIB_UNSET) {
|
|
add_pbf_error(s, "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) {
|
|
add_pbf_error(s, "A meridian could not be found", string, begin);
|
|
} else {
|
|
s->time->h += tmp;
|
|
}
|
|
break;
|
|
case 'i': /* two digit minute, with leading zero */
|
|
{
|
|
int length;
|
|
timelib_sll min;
|
|
|
|
TIMELIB_CHECK_NUMBER;
|
|
min = timelib_get_nr_ex((char **) &ptr, 2, &length);
|
|
if (min == TIMELIB_UNSET || length != 2) {
|
|
add_pbf_error(s, "A two digit minute could not be found", string, begin);
|
|
} else {
|
|
s->time->i = min;
|
|
}
|
|
}
|
|
break;
|
|
case 's': /* two digit second, with leading zero */
|
|
{
|
|
int length;
|
|
timelib_sll sec;
|
|
|
|
TIMELIB_CHECK_NUMBER;
|
|
sec = timelib_get_nr_ex((char **) &ptr, 2, &length);
|
|
if (sec == TIMELIB_UNSET || length != 2) {
|
|
add_pbf_error(s, "A two second minute could not be found", string, begin);
|
|
} else {
|
|
s->time->s = sec;
|
|
}
|
|
}
|
|
break;
|
|
case 'u': /* up to six digit millisecond */
|
|
{
|
|
double f;
|
|
char *tptr;
|
|
|
|
TIMELIB_CHECK_NUMBER;
|
|
tptr = ptr;
|
|
if ((f = timelib_get_nr((char **) &ptr, 6)) == TIMELIB_UNSET || (ptr - tptr < 1)) {
|
|
add_pbf_error(s, "A six digit millisecond could not be found", string, begin);
|
|
} else {
|
|
s->time->f = (f / pow(10, (ptr - tptr)));
|
|
}
|
|
}
|
|
break;
|
|
case ' ': /* any sort of whitespace (' ' and \t) */
|
|
timelib_eat_spaces((char **) &ptr);
|
|
break;
|
|
case 'U': /* epoch seconds */
|
|
TIMELIB_CHECK_NUMBER;
|
|
TIMELIB_HAVE_RELATIVE();
|
|
tmp = timelib_get_unsigned_nr((char **) &ptr, 24);
|
|
s->time->y = 1970;
|
|
s->time->m = 1;
|
|
s->time->d = 1;
|
|
s->time->h = s->time->i = s->time->s = 0;
|
|
s->time->f = 0.0;
|
|
s->time->relative.s += tmp;
|
|
s->time->is_localtime = 1;
|
|
s->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
|
|
s->time->z = 0;
|
|
break;
|
|
|
|
case 'e': /* timezone */
|
|
case 'P': /* timezone */
|
|
case 'T': /* timezone */
|
|
case 'O': /* timezone */
|
|
{
|
|
int tz_not_found;
|
|
s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
|
|
if (tz_not_found) {
|
|
add_pbf_error(s, "The timezone could not be found in the database", string, begin);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case '#': /* separation symbol */
|
|
if (*ptr == ';' || *ptr == ':' || *ptr == '/' || *ptr == '.' || *ptr == ',' || *ptr == '-' || *ptr == '(' || *ptr == ')') {
|
|
++ptr;
|
|
} else {
|
|
add_pbf_error(s, "The separation symbol ([;:/.,-]) could not be found", string, begin);
|
|
}
|
|
break;
|
|
|
|
case ';':
|
|
case ':':
|
|
case '/':
|
|
case '.':
|
|
case ',':
|
|
case '-':
|
|
case '(':
|
|
case ')':
|
|
if (*ptr == *fptr) {
|
|
++ptr;
|
|
} else {
|
|
add_pbf_error(s, "The separation symbol could not be found", string, begin);
|
|
}
|
|
break;
|
|
|
|
case '!': /* 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 */
|
|
timelib_time_reset_unset_fields(s->time);
|
|
break; /* break intentionally not missing */
|
|
|
|
case '?': /* random char */
|
|
++ptr;
|
|
break;
|
|
|
|
case '\\': /* escaped char */
|
|
*fptr++;
|
|
if (*ptr == *fptr) {
|
|
++ptr;
|
|
} else {
|
|
add_pbf_error(s, "The escaped character could not be found", string, begin);
|
|
}
|
|
break;
|
|
|
|
case '*': /* 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;
|
|
break;
|
|
|
|
default:
|
|
if (*fptr != *ptr) {
|
|
add_pbf_error(s, "The format separator does not match", string, begin);
|
|
}
|
|
ptr++;
|
|
}
|
|
fptr++;
|
|
}
|
|
if (*ptr) {
|
|
if (allow_extra) {
|
|
add_pbf_warning(s, "Trailing data", string, ptr);
|
|
} else {
|
|
add_pbf_error(s, "Trailing data", string, ptr);
|
|
}
|
|
}
|
|
/* ignore trailing +'s */
|
|
while (*fptr == '+') {
|
|
fptr++;
|
|
}
|
|
if (*fptr) {
|
|
/* Trailing | and ! specifiers are valid. */
|
|
int done = 0;
|
|
while (*fptr && !done) {
|
|
switch (*fptr++) {
|
|
case '!': /* reset all fields to default */
|
|
timelib_time_reset_fields(s->time);
|
|
break;
|
|
|
|
case '|': /* reset all fields to default when not set */
|
|
timelib_time_reset_unset_fields(s->time);
|
|
break;
|
|
|
|
default:
|
|
add_pbf_error(s, "Data missing", string, ptr);
|
|
done = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 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->h = 0;
|
|
}
|
|
if (s->time->i == TIMELIB_UNSET ) {
|
|
s->time->i = 0;
|
|
}
|
|
if (s->time->s == TIMELIB_UNSET ) {
|
|
s->time->s = 0;
|
|
}
|
|
}
|
|
|
|
/* do funky checking whether the parsed time was valid time */
|
|
if (s->time->h != TIMELIB_UNSET && s->time->i != TIMELIB_UNSET &&
|
|
s->time->s != TIMELIB_UNSET &&
|
|
!timelib_valid_time( s->time->h, s->time->i, s->time->s)) {
|
|
add_pbf_warning(s, "The parsed time was invalid", string, ptr);
|
|
}
|
|
/* do funky checking whether the parsed date was valid date */
|
|
if (s->time->y != TIMELIB_UNSET && s->time->m != TIMELIB_UNSET &&
|
|
s->time->d != TIMELIB_UNSET &&
|
|
!timelib_valid_date( s->time->y, s->time->m, s->time->d)) {
|
|
add_pbf_warning(s, "The parsed date was invalid", string, ptr);
|
|
}
|
|
|
|
if (errors) {
|
|
*errors = in.errors;
|
|
} else {
|
|
timelib_error_container_dtor(in.errors);
|
|
}
|
|
return in.time;
|
|
}
|
|
|
|
void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options)
|
|
{
|
|
if (!(options & TIMELIB_OVERRIDE_TIME) && parsed->have_date && !parsed->have_time) {
|
|
parsed->h = 0;
|
|
parsed->i = 0;
|
|
parsed->s = 0;
|
|
parsed->f = 0;
|
|
}
|
|
if (parsed->y == TIMELIB_UNSET) parsed->y = now->y != TIMELIB_UNSET ? now->y : 0;
|
|
if (parsed->d == TIMELIB_UNSET) parsed->d = now->d != TIMELIB_UNSET ? now->d : 0;
|
|
if (parsed->m == TIMELIB_UNSET) parsed->m = now->m != TIMELIB_UNSET ? now->m : 0;
|
|
if (parsed->h == TIMELIB_UNSET) parsed->h = now->h != TIMELIB_UNSET ? now->h : 0;
|
|
if (parsed->i == TIMELIB_UNSET) parsed->i = now->i != TIMELIB_UNSET ? now->i : 0;
|
|
if (parsed->s == TIMELIB_UNSET) parsed->s = now->s != TIMELIB_UNSET ? now->s : 0;
|
|
if (parsed->f == TIMELIB_UNSET) parsed->f = now->f != TIMELIB_UNSET ? now->f : 0;
|
|
if (parsed->z == TIMELIB_UNSET) parsed->z = now->z != TIMELIB_UNSET ? now->z : 0;
|
|
if (parsed->dst == TIMELIB_UNSET) parsed->dst = now->dst != TIMELIB_UNSET ? now->dst : 0;
|
|
|
|
if (!parsed->tz_abbr) {
|
|
parsed->tz_abbr = now->tz_abbr ? strdup(now->tz_abbr) : NULL;
|
|
}
|
|
if (!parsed->tz_info) {
|
|
parsed->tz_info = now->tz_info ? (!(options & TIMELIB_NO_CLONE) ? timelib_tzinfo_clone(now->tz_info) : now->tz_info) : NULL;
|
|
}
|
|
if (parsed->zone_type == 0 && now->zone_type != 0) {
|
|
parsed->zone_type = now->zone_type;
|
|
/* parsed->tz_abbr = now->tz_abbr ? strdup(now->tz_abbr) : NULL;
|
|
parsed->tz_info = now->tz_info ? timelib_tzinfo_clone(now->tz_info) : NULL;
|
|
*/ parsed->is_localtime = 1;
|
|
}
|
|
/* timelib_dump_date(parsed, 2);
|
|
timelib_dump_date(now, 2);
|
|
*/
|
|
}
|
|
|
|
char *timelib_timezone_id_from_abbr(const char *abbr, long gmtoffset, int isdst)
|
|
{
|
|
const timelib_tz_lookup_table *tp;
|
|
|
|
tp = zone_search(abbr, gmtoffset, isdst);
|
|
if (tp) {
|
|
return (tp->full_tz_name);
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
const timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void)
|
|
{
|
|
return timelib_timezone_lookup;
|
|
}
|
|
|
|
#ifdef DEBUG_PARSER_STUB
|
|
int main(void)
|
|
{
|
|
timelib_time time = timelib_strtotime("May 12");
|
|
|
|
printf ("%04d-%02d-%02d %02d:%02d:%02d.%-5d %+04d %1d",
|
|
time.y, time.m, time.d, time.h, time.i, time.s, time.f, time.z, time.dst);
|
|
if (time.have_relative) {
|
|
printf ("%3dY %3dM %3dD / %3dH %3dM %3dS",
|
|
time.relative.y, time.relative.m, time.relative.d, time.relative.h, time.relative.i, time.relative.s);
|
|
}
|
|
if (time.have_weekday_relative) {
|
|
printf (" / %d", time.relative.weekday);
|
|
}
|
|
if (time.have_weeknr_day) {
|
|
printf(" / %dW%d", time.relative.weeknr_day.weeknr, time.relative.weeknr_day.dayofweek);
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* vim: syntax=c
|
|
*/
|