Further WIP on tidy up and merge beginning of new manipulation infrastructur
This commit is contained in:
parent
603b067310
commit
35c4455bc2
|
@ -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
|
/* options for text editors
|
||||||
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
||||||
vim: expandtab:ts=4:sw=4
|
vim: expandtab:ts=4:sw=4
|
||||||
|
|
|
@ -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 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;
|
int y = 0, m = -1, d = -1, w = -1, wd = -1, hour = -1, min = -1, sec = -1, tz_sec = 0;
|
||||||
double frac;
|
double frac;
|
||||||
|
struct iso8601_elapsed elapsed;
|
||||||
|
|
||||||
if(earliest) memset(earliest, 0, sizeof(struct iso8601_date));
|
if(earliest) memset(earliest, 0, sizeof(struct iso8601_date));
|
||||||
if(latest) memset(latest, 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
|
/* 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. */
|
* requested), and ensure that any leap second requested was a valid leap second. */
|
||||||
if(details) details->tz_sec = tz_sec;
|
if(details) details->tz_sec = tz_sec;
|
||||||
if(tz_sec && earliest) iso8601_add_seconds(earliest, - leap_sec_req - tz_sec);
|
if(tz_sec && earliest) {
|
||||||
if(tz_sec && latest) iso8601_add_seconds(latest, - leap_sec_req - tz_sec);
|
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) {
|
if(leap_sec_req) {
|
||||||
ERROR_IF(earliest && earliest->sec != 86400);
|
ERROR_IF(earliest && earliest->sec != 86400);
|
||||||
ERROR_IF(latest && latest->sec != 86400);
|
ERROR_IF(latest && latest->sec != 86400);
|
||||||
|
|
|
@ -23,6 +23,7 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date,
|
||||||
struct iso8601_date dttz;
|
struct iso8601_date dttz;
|
||||||
double frac;
|
double frac;
|
||||||
char* str_orig;
|
char* str_orig;
|
||||||
|
struct iso8601_elapsed elapsed;
|
||||||
|
|
||||||
str_orig = str;
|
str_orig = str;
|
||||||
|
|
||||||
|
@ -31,7 +32,11 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date,
|
||||||
|
|
||||||
// adjust output for timezone
|
// adjust output for timezone
|
||||||
dttz = *date;
|
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
|
// determine whether or not to force extended output
|
||||||
iso8601_to_cal(&y, &m, &d, &dttz);
|
iso8601_to_cal(&y, &m, &d, &dttz);
|
||||||
|
|
|
@ -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
|
||||||
|
*/
|
|
@ -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
|
|
||||||
*/
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* libiso8601/src/libiso8601/manip.c
|
/* libiso8601/src/libiso8601/400_manip.c
|
||||||
*
|
*
|
||||||
* (c)2006, Laurence Withers, <l@lwithers.me.uk>.
|
* (c)2006, Laurence Withers, <l@lwithers.me.uk>.
|
||||||
* Released under the GNU GPLv2. See file COPYING or
|
* 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;
|
/* TODO */
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
/* TODO */
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 < \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
|
||||||
|
*/
|
Loading…
Reference in New Issue