From 6a55a6369560948eec984a177303e15dc9b6a1d5 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Sat, 25 Nov 2006 00:57:31 +0000 Subject: [PATCH] WIP on leap second support --- src/libiso8601/build.monolithic | 2 +- src/libiso8601/functions.h | 41 +++++++++++++++++- src/libiso8601/leap.c | 76 +++++++++++++++++++++++++++++++++ src/libiso8601/parser.c | 17 ++++++++ 4 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 src/libiso8601/leap.c diff --git a/src/libiso8601/build.monolithic b/src/libiso8601/build.monolithic index 9245773..b3451a4 100644 --- a/src/libiso8601/build.monolithic +++ b/src/libiso8601/build.monolithic @@ -11,7 +11,7 @@ then MONOLITHIC_SOURCE="$(echo src/libiso8601/{TopHeader,types,functions,BottomHeader}.h)" make_monolithic ${HDR} Ch || return 1 - MONOLITHIC_SOURCE="$(echo src/libiso8601/{TopSource,c_library,calc,parser,print,manip}.c)" + MONOLITHIC_SOURCE="$(echo src/libiso8601/{TopSource,c_library,calc,parser,print,manip,leap}.c)" make_monolithic ${SRC} C || return 1 libiso8601_MONOLITHIC=1 diff --git a/src/libiso8601/functions.h b/src/libiso8601/functions.h index c49872f..a40d262 100644 --- a/src/libiso8601/functions.h +++ b/src/libiso8601/functions.h @@ -5,10 +5,45 @@ * http://www.gnu.org/copyleft/gpl.html for details. */ -/* parse.c */ + + +/*! \defgroup parse Parsing and validation routines. + +These routines are used for parsing an ISO8601 date/time string into the internal structure used +to represent them, and for validating such dates/times. + +*/ +/*!@{*/ + +/*! \brief Parse ISO8601 date/time. + +\param str The input string. +\param[out] earliest ... +\param[out] latest The latest possible time the string could represent. May be 0. +\param[out] details Stores details such as the precision to which the time/date were specified. May + be 0. +\retval -1 on error (and see \a errno). +\retval 0 on success. + +Parses a string containing the ISO8601 date/time. Deals with any format of date, optionally storing +the details in \a details. The time may be partial, in which case this function returns the earliest +and latest times that could possibly be represented by the string. + +Note that this function will accept leap seconds (23:59:60) on days on which they occurred. It will +also accept the 24:00:00 representation of midnight (end of day). + +\todo Strip whitespace. + +*/ int iso8601_parse(const char* str, struct iso8601_date* earliest, struct iso8601_date* latest, struct iso8601_details* details); +int iso8601_valid(const struct iso8601_date* date); + +/*!@}*/ + + + /* c_library.c */ void iso8601_now(struct iso8601_date* date, struct iso8601_details* details); void iso8601_from_ts(struct iso8601_date* date, const struct timespec* ts); @@ -34,6 +69,10 @@ void iso8601_print(char* str, int amt, const struct iso8601_date* date, /* manip.c */ void iso8601_add_seconds(struct iso8601_date* date, long seconds); +/* leap.c */ +int iso8601_seconds_leap(const struct iso8601_date* date); +int iso8601_valid_leap(const struct iso8601_date* date); + /* options for text editors kate: replace-trailing-space-save true; space-indent true; tab-width 4; vim: expandtab:ts=4:sw=4 diff --git a/src/libiso8601/leap.c b/src/libiso8601/leap.c new file mode 100644 index 0000000..18c08df --- /dev/null +++ b/src/libiso8601/leap.c @@ -0,0 +1,76 @@ +/* libiso8601/src/libiso8601/TopSource.c + * + * (c)2006, Laurence Withers, . + * Released under the GNU GPLv2. See file COPYING or + * http://www.gnu.org/copyleft/gpl.html for details. +*/ + + + +static int leap_second_days[] = { + 720439, // 19720630 + 720623, // 19721231 + 720988, // 19731231 + 721353, // 19741231 + 721718, // 19751231 + 722084, // 19761231 + 722449, // 19771231 + 722814, // 19781231 + 723179, // 19791231 + 723726, // 19810630 + 724091, // 19820630 + 724456, // 19830630 + 725187, // 19850630 + 726101, // 19871231 + 726832, // 19891231 + 727197, // 19901231 + 727744, // 19920630 + 728109, // 19930630 + 728474, // 19940630 + 729023, // 19951231 + 729570, // 19970630 + 730119, // 19981231 + 732676 // 19991231 +}; + + + +int iso8601_seconds_leap(const struct iso8601_date* date) +{ + int num_ly = 0, i = 0; + + num_ly = sizeof(leap_second_days) / sizeof(int); + for(i = 0; i < num_ly; ++i) if(leap_second_days[i] == date->day) return 86401; + return 86400; +} + + + +int iso8601_valid_leap(const struct iso8601_date* date) +{ + int num_ly = 0, i = 0; + + if(date->nsec < 0 || date->nsec >= 1000000000) return 0; + + switch(date->sec) { + case 0 ... 86399: + return 1; + + case 86400: /* 23:59:60 */ + num_ly = sizeof(leap_second_days) / sizeof(int); + for(i = 0; i < num_ly; ++i) if(leap_second_days[i] == date->day) return 1; + return 0; + + case 86401: /* 24:00:00 */ + return !date->nsec; + } + + return 0; +} + + + +/* options for text editors +kate: replace-trailing-space-save true; space-indent true; tab-width 4; +vim: expandtab:ts=4:sw=4 +*/ diff --git a/src/libiso8601/parser.c b/src/libiso8601/parser.c index 60b61e2..5e4b841 100644 --- a/src/libiso8601/parser.c +++ b/src/libiso8601/parser.c @@ -634,6 +634,23 @@ done: +int iso8601_valid(const struct iso8601_date* date) +{ + if(date->nsec < 0 || date->nsec > 1000000000) return 0; + + switch(date->sec) { + case 0 ... 86399: + return 1; + + case 86401: /* 24:00:00 */ + return !date->nsec; + } + + return 0; +} + + + /* options for text editors kate: replace-trailing-space-save true; space-indent true; tab-width 4; vim: expandtab:ts=4:sw=4