Further WIP on tidy up and merge beginning of new manipulation infrastructur

This commit is contained in:
Laurence Withers 2007-07-23 16:55:13 +00:00
parent 603b067310
commit 35c4455bc2
7 changed files with 269 additions and 76 deletions

View File

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

View File

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

View File

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

151
src/libiso8601/400_calc.h Normal file
View File

@ -0,0 +1,151 @@
/* libiso8601/src/libiso8601/400_calc.h
*
* (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.
*/
/*! \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
*/

View File

@ -1,33 +0,0 @@
/* libiso8601/src/libiso8601/functions.h
*
* (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.
*/
/* 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
*/

View File

@ -1,4 +1,4 @@
/* libiso8601/src/libiso8601/manip.c
/* libiso8601/src/libiso8601/400_manip.c
*
* (c)2006, Laurence Withers, <l@lwithers.me.uk>.
* 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 */
}

View File

@ -0,0 +1,80 @@
/* libiso8601/src/libiso8601/400_manip.h
*
* (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.
*/
/*! \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 &lt; \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 &lte; \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
*/