WIP on leap second support

This commit is contained in:
Laurence Withers 2006-11-25 00:57:31 +00:00
parent 6a64114854
commit 6a55a63695
4 changed files with 134 additions and 2 deletions

View File

@ -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

View File

@ -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

76
src/libiso8601/leap.c Normal file
View File

@ -0,0 +1,76 @@
/* libiso8601/src/libiso8601/TopSource.c
*
* (c)2006, Laurence Withers, <l@lwithers.me.uk>.
* 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
*/

View File

@ -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