diff --git a/src/libiso8601/100_types.h b/src/libiso8601/100_types.h index f0d38d0..253dfa3 100644 --- a/src/libiso8601/100_types.h +++ b/src/libiso8601/100_types.h @@ -103,6 +103,22 @@ struct iso8601_details { +/*! \brief Short period elapsed time. + +This structure contains the details of an elapsed time period, split into seconds and nanoseconds. +None of its components can ever be negative. This is only capable of representing short (compared to +struct iso8601_date's range) periods of up to approximately 136 years. + +*/ +struct iso8601_elapsed { + /* number of whole days elapsed */ + uint32_t day; + uint32_t sec; + uint32_t nsec; +}; + + + /* 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/200_parser.c b/src/libiso8601/200_parser.c index 82927d2..8a8aba9 100644 --- a/src/libiso8601/200_parser.c +++ b/src/libiso8601/200_parser.c @@ -37,6 +37,7 @@ int iso8601_parse(const char* str, struct iso8601_date* earliest, struct iso8601 int num = 0, neg = 0, dig = 0, tz_neg = 0, nsec = -1, nsec_dig = -1, leap_sec_req = 0; int y = 0, m = -1, d = -1, w = -1, wd = -1, hour = -1, min = -1, sec = -1, tz_sec = 0; double frac; + struct iso8601_elapsed elapsed; if(earliest) memset(earliest, 0, sizeof(struct iso8601_date)); if(latest) memset(latest, 0, sizeof(struct iso8601_date)); @@ -651,8 +652,16 @@ done: /* correct for timezone offset (note trickery to end up at 23:59:60 iff a leap second was * requested), and ensure that any leap second requested was a valid leap second. */ if(details) details->tz_sec = tz_sec; - if(tz_sec && earliest) iso8601_add_seconds(earliest, - leap_sec_req - tz_sec); - if(tz_sec && latest) iso8601_add_seconds(latest, - leap_sec_req - tz_sec); + if(tz_sec && earliest) { + elapsed.sec = leap_sec_req + tz_sec; + elapsed.nsec = 0; + iso8601_subtract_elapsed(earliest, &elapsed); + } + if(tz_sec && latest) { + elapsed.sec = leap_sec_req + tz_sec; + elapsed.nsec = 0; + iso8601_subtract_elapsed(latest, &elapsed); + } if(leap_sec_req) { ERROR_IF(earliest && earliest->sec != 86400); ERROR_IF(latest && latest->sec != 86400); diff --git a/src/libiso8601/200_print.c b/src/libiso8601/200_print.c index 0287820..69786a1 100644 --- a/src/libiso8601/200_print.c +++ b/src/libiso8601/200_print.c @@ -23,6 +23,7 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date, struct iso8601_date dttz; double frac; char* str_orig; + struct iso8601_elapsed elapsed; str_orig = str; @@ -31,7 +32,11 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date, // adjust output for timezone dttz = *date; - if(details->tz_sec) iso8601_add_seconds(&dttz, details->tz_sec); + if(details->tz_sec) { + elapsed.sec = details ? details->tz_sec : 0; + elapsed.nsec = 0; + iso8601_add_elapsed(&dttz, &elapsed); + } // determine whether or not to force extended output iso8601_to_cal(&y, &m, &d, &dttz); diff --git a/src/libiso8601/400_calc.h b/src/libiso8601/400_calc.h new file mode 100644 index 0000000..11efb70 --- /dev/null +++ b/src/libiso8601/400_calc.h @@ -0,0 +1,151 @@ +/* libiso8601/src/libiso8601/400_calc.h + * + * (c)2006, Laurence Withers, . + * Released under the GNU GPLv2. See file COPYING or + * http://www.gnu.org/copyleft/gpl.html for details. +*/ + + + +/*! \defgroup manip Conversion and calculation routines. + +This set of functions is useful for converting dates and times into formats understood by humans, +and vice versa. + +*/ +/*!@{*/ + + + +/*! \brief Is year a leap year? + +\param year Year to examine. +\retval 0 if not leap year. +\retval non-0 if leap year. + +Returns non-0 if \a year is a leap year. + +*/ +int iso8601_isleap(int year); + + + +/*! \brief Convert date to calendar format. + +\param[out] year Calendar year. +\param[out] month Calendar month (1 to 12). +\param[out] day Calendar day (starting from 1). +\param date Date to convert. + +*/ +void iso8601_to_cal(int* year, int* month, int* day, const struct iso8601_date* date); + + + +/*! \brief Convert date from calendar format. + +\param[out] date Output date. +\param year Calendar year. +\param month Calendar month (1 to 12). +\param day Calenday day (starting from 1). +\retval 0 on success. +\retval -1 on error (and see \a errno). + +Converts the date specified in \a year, \a month and \a day into \a date. Does not touch the \a sec +or \a nsec time members of \a date. + +*/ +int iso8601_from_cal(struct iso8601_date* date, int year, int month, int day); + + + +/*! \brief Convert date to ordinal format. + +\param[out] year Calendar year. +\param[out] oday Ordinal day (from 1). +\param date Date to convert. + +*/ +void iso8601_to_ord(int* year, int* oday, const struct iso8601_date* date); + + + +/*! \brief Convert date from ordinal format. + +\param[out] date Output date. +\param year Calendar year. +\param day Ordinal day (from 1). +\retval 0 on success. +\retval -1 on error (and see \a errno). + +Converts the date specified into \a year and \a oday into \a date. Does not touch the \a sec or +\a nsec time members of \a date. + +*/ +int iso8601_from_ord(struct iso8601_date* date, int year, int oday); + + + +/*! \brief Convert date to week format. + +\param[out] year Calendar year. +\param[out] week ISO week number (from 1). +\param[out] wday ISO week day number (1 = Monday, 7 = Sunday). +\param date Date to convert. + +*/ +void iso8601_to_week(int* year, int* week, int* wday, const struct iso8601_date* date); + + + +/*! \brief Convert date from week format. + +\param [out] date Output date. +\param year Calendar year. +\param week ISO week number (from 1). +\param wday ISO week day number (1 = Monday, 7 = Sunday). +\retval 0 on success. +\retval -1 on error (and see \a errno). + +*/ +int iso8601_from_week(struct iso8601_date* date, int year, int week, int wday); + + + +/*! \brief Convert time to wall clock format. + +\param[out] hour Output hour. +\param[out] min Output minute. +\param[out] sec Output second. +\param date Date/time to convert. + +Converts the time stored in \a date into wall clock format, storing the result in \a hour, \a min +and \a sec. + +*/ +void iso8601_to_clocktime(int* hour, int* min, int* sec, const struct iso8601_date* date); + + + +/*! \brief Convert time from wall clock format. + +\param[out] Output time. +\param hour Hour. +\param min Minute. +\param sec Second. +\retval 0 on success. +\retval -1 on error (and see \a errno). + +Converts the time as specified by \a hour, \a min and \a sec, storing the result in \a date. Does +not touch the \a day (date) member of \a date. + +*/ +int iso8601_from_clocktime(struct iso8601_date* date, int hour, int min, int sec); + + + +/*!@}*/ +/* 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/400_functions.h b/src/libiso8601/400_functions.h deleted file mode 100644 index 2996eaa..0000000 --- a/src/libiso8601/400_functions.h +++ /dev/null @@ -1,33 +0,0 @@ -/* libiso8601/src/libiso8601/functions.h - * - * (c)2006, Laurence Withers, . - * Released under the GNU GPLv2. See file COPYING or - * http://www.gnu.org/copyleft/gpl.html for details. -*/ - -/* calc.c */ -int iso8601_isleap(int year); -void iso8601_to_cal(int* year, int* month, int* day, const struct iso8601_date* date); -int iso8601_from_cal(struct iso8601_date* date, int year, int month, int day); -void iso8601_to_ord(int* year, int* oday, const struct iso8601_date* date); -int iso8601_from_ord(struct iso8601_date* date, int year, int oday); -void iso8601_to_week(int* year, int* week, int* wday, const struct iso8601_date* date); -int iso8601_from_week(struct iso8601_date* date, int year, int week, int wday); -void iso8601_to_clocktime(int* hour, int* min, int* sec, const struct iso8601_date* date); -int iso8601_from_clocktime(struct iso8601_date* date, int hour, int min, int sec); - -/* manip.c */ -int iso8601_lt(const struct iso8601_date* d1, const struct iso8601_date* d2); -int iso8601_lte(const struct iso8601_date* d1, const struct iso8601_date* d2); -int iso8601_eq(const struct iso8601_date* d1, const struct iso8601_date* d2); -void iso8601_add_seconds(struct iso8601_date* date, long seconds); -void iso8601_add_nanoseconds(struct iso8601_date* date, long nano); - -/* leap.c */ -int iso8601_seconds_leap(const struct iso8601_date* date); -int iso8601_leap_elapsed(const struct iso8601_date* start, const struct iso8601_date* end); - -/* 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/manip.c b/src/libiso8601/400_manip.c similarity index 50% rename from src/libiso8601/manip.c rename to src/libiso8601/400_manip.c index 34873ab..1ab5fd9 100644 --- a/src/libiso8601/manip.c +++ b/src/libiso8601/400_manip.c @@ -1,4 +1,4 @@ -/* libiso8601/src/libiso8601/manip.c +/* libiso8601/src/libiso8601/400_manip.c * * (c)2006, Laurence Withers, . * Released under the GNU GPLv2. See file COPYING or @@ -38,51 +38,16 @@ int iso8601_eq(const struct iso8601_date* d1, const struct iso8601_date* d2) -void iso8601_add_seconds(struct iso8601_date* date, long seconds) +void iso8601_add_elapsed(struct iso8601_date* date, const struct iso8601_elapsed* per) { - int sday; - ldiv_t qr; - - sday = date->day; - qr = ldiv(seconds + date->sec, 86400); - date->day += qr.quot; - - date->sec = qr.rem; - if(date->sec < 0) { - --date->day; - date->sec += 86400; - } - - /* leap second correction */ - if(sday != date->day) { - date->sec += _leap_elapsed_day(sday, date->day); - if(date->sec < 0) { - --date->day; - date->sec += iso8601_seconds_leap(date); - } else if(date->sec >= iso8601_seconds_leap(date)) { - date->sec -= iso8601_seconds_leap(date); - ++date->day; - } - } + /* TODO */ } -void iso8601_add_nanoseconds(struct iso8601_date* date, long nsec) +void iso8601_subtract_elapsed(struct iso8601_date* date, const struct iso8601_elapsed* per) { - ldiv_t qr; - - qr = ldiv(nsec, BILLION); - date->nsec += qr.rem; - if(date->nsec > BILLION) { - date->nsec -= BILLION; - ++qr.quot; - } else if(date->nsec < 0) { - date->nsec += BILLION; - --qr.quot; - } - - iso8601_add_seconds(date, qr.quot); + /* TODO */ } diff --git a/src/libiso8601/400_manip.h b/src/libiso8601/400_manip.h new file mode 100644 index 0000000..0b75666 --- /dev/null +++ b/src/libiso8601/400_manip.h @@ -0,0 +1,80 @@ +/* libiso8601/src/libiso8601/400_manip.h + * + * (c)2006, Laurence Withers, . + * Released under the GNU GPLv2. See file COPYING or + * http://www.gnu.org/copyleft/gpl.html for details. +*/ + + + +/*! \defgroup manip Manipulation routines. + +This set of functions is useful for converting dates and times into formats understood by humans, +and vice versa. + +*/ +/*!@{*/ + + + +/*! \brief Comparison (less than). + +\param d1 First date to compare. +\param d2 Second date to compare. +\retval non-0 if \a d1 < \a d2 +\retval 0 otherwise + +*/ +int iso8601_lt(const struct iso8601_date* d1, const struct iso8601_date* d2); + + + +/*! \brief Comparison (less than or equal to). + +\param d1 First date to compare. +\param d2 Second date to compare. +\retval non-0 if \a d1 <e; \a d2 +\retval 0 otherwise + +*/ +int iso8601_lte(const struct iso8601_date* d1, const struct iso8601_date* d2); + + + +/*! \brief Comparison (equality). + +\param d1 First date to compare. +\param d2 Second date to compare. +\retval non-0 if \a d1 == \a d2 +\retval 0 otherwise + +*/ +int iso8601_eq(const struct iso8601_date* d1, const struct iso8601_date* d2); + + + +/*! \brief Add a period to a date. + +\param[in,out] date Date to modify. +\param per Period to advance date/time by. + +*/ +void iso8601_add_elapsed(struct iso8601_date* date, const struct iso8601_elapsed* per); + + + +/*! \brief Subtract a period from a date. + +\param[in,out] date Date to modify. +\param per Period to regress date/time by. + +*/ +void iso8601_subtract_elapsed(struct iso8601_date* date, const struct iso8601_elapsed* per); + + + +/*!@}*/ +/* options for text editors +kate: replace-trailing-space-save true; space-indent true; tab-width 4; +vim: expandtab:ts=4:sw=4 +*/