Compare commits

..

37 Commits

Author SHA1 Message Date
Laurence Withers 82aa0f2f20 Bump version 2015-06-12 11:01:21 +01:00
Laurence Withers 2e610c4db3 Add 2015-06-30 leap second to built-in table 2015-06-12 10:55:53 +01:00
Laurence Withers dd3fe182af Update build system (Doxyfile) 2015-06-12 10:53:31 +01:00
Laurence Withers 0d5c2078b3 Bump version 2013-04-05 09:35:19 +00:00
Laurence Withers 6b25293f35 Fix build system ordering
Make sure that the library is built before either of the isodate or setisodate
apps, otherwise we end up with problems compiling from scratch.
2013-04-05 09:32:22 +00:00
Laurence Withers dcb15f2081 Bump version 2012-01-07 17:42:57 +00:00
Laurence Withers 4c470ec1e9 Bump version 2012-01-07 17:42:57 +00:00
Laurence Withers ba81c458e1 Update for 2012-06-30 leap second 2012-01-07 17:42:44 +00:00
Laurence Withers 49536349f7 Bump version 2011-11-18 12:19:09 +00:00
Laurence Withers c7b38eab5a Bump version 2011-11-18 12:19:09 +00:00
Laurence Withers c198eaf34b Remove accidental variable definition 2011-11-16 12:04:15 +00:00
Laurence Withers b622223b64 Remove unneeded nonnull attribute 2011-11-16 09:58:21 +00:00
Laurence Withers 81df4e8a05 Add C++ extern C include guards 2011-11-15 16:49:46 +00:00
Laurence Withers 7a5f30bfcd Update build system 2011-11-15 16:49:46 +00:00
Laurence Withers d910e88bc3 Bump version 2010-08-02 12:01:43 +00:00
Laurence Withers 2aa3d5aaac Bump version 2010-08-02 12:01:43 +00:00
Laurence Withers d013bff263 Remove incorrect nonnull attribute
iso8601_leap_table_load() had an incorrect ‘nonnull’ attribute, which could
lead to crashes as the compiled code could omit the test for null which then
substitutes the system default. Fix it by removing the attribute.
2010-08-02 12:00:20 +00:00
Laurence Withers 8cc71fb069 Bump version 2010-06-18 12:49:36 +00:00
Laurence Withers 2d9621e0a5 Bump version 2010-06-18 12:49:33 +00:00
Laurence Withers 944331702f Cope with negative C library timestamps
While perhaps not strictly valid, negative timestamps can potentially be
returned by the C library and passed in to iso8601_from_ts() etc. This commit
adds a check for such timestamps and copes with the gracefully, whereas
previously invalid ISO8601 timestamps would have been generated.
2010-06-18 12:47:38 +00:00
Laurence Withers 0d56edd890 Bump version 2010-01-28 16:22:46 +00:00
Laurence Withers 65fe613272 Bump version 2010-01-28 16:22:39 +00:00
Laurence Withers 64e06d17c4 Add explicit note on params which may be null 2010-01-28 16:22:03 +00:00
Laurence Withers cd9a2d252a iso8601_difference(): incorrect nonnull attribute
iso8601_difference was incorrectly marked as having all of its attributes
required to be non-null, but this is not the case according to the docs or
the implementation. This was causing a crash as the compiled library was
taking advantage of the nonnull notation to remove some tests against null
which, according to the docs, are actually required.

Fix by tightening the nonnull specification to those parameters which actually
require it.
2010-01-28 16:17:53 +00:00
Laurence Withers ed05b5c872 Bump version 2010-01-08 19:26:21 +00:00
Laurence Withers bd4ddd7621 Write brief description for library
Add a brief description of the library on the doxygen front page.
2010-01-08 19:25:58 +00:00
Laurence Withers 420df40a5b Bring C code up to coding standards
Reformatting and comment improvement only. No code changes.
2010-01-08 19:22:36 +00:00
Laurence Withers 9f3fbd4116 Minor build system update
A fix for when there are multiple libraries in a single package. Doesn't apply
here but just in case.
2010-01-08 18:49:50 +00:00
Laurence Withers 6285d214aa Documentation and annotation updates
This commit updates the Doxygen documentation (particularly taking into account
a request from Kelly Dunlop for more verbose notice about which members are
changed by iso8601_from_*()) and file/function annotation/formatting to current
standards.
2010-01-08 18:46:34 +00:00
Laurence Withers e504a722f5 Bump version 2009-05-29 14:52:52 +00:00
Laurence Withers 1a0553e083 Bump version 2009-05-29 14:52:52 +00:00
Laurence Withers 7ba82a2988 Add default path for iso8601_leap_table_load() 2009-05-29 14:51:26 +00:00
Laurence Withers b7d039a32c Add iso8601_elapsed_divide() 2009-05-29 14:51:14 +00:00
Laurence Withers dcfc699af0 Bump version 2009-04-06 14:58:26 +00:00
Laurence Withers 47ccc537b8 Bump version 2009-04-06 14:58:26 +00:00
Laurence Withers 1d9447dcd2 Add iso8601_cmp(), comparison function for qsort() 2009-04-06 14:58:05 +00:00
Laurence Withers d09e55e8ae Update build system 2009-04-06 14:56:00 +00:00
40 changed files with 3028 additions and 495 deletions

2
config
View File

@ -32,5 +32,7 @@
source "scripts/paths" source "scripts/paths"
# Project-specific variables below. # Project-specific variables below.
[ -z "${DEFAULT_LEAP_TABLE}" ] && DEFAULT_LEAP_TABLE="${SHAREDIR}/libiso8601/leap-table"
[ -z "${CC}" ] && CC="gcc" [ -z "${CC}" ] && CC="gcc"
[ -z "${CFLAGS}" ] && CFLAGS="-g -O2 -W -Wall" [ -z "${CFLAGS}" ] && CFLAGS="-g -O2 -W -Wall"

11
make.sh
View File

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/bash
# libiso8601/make.sh # libiso8601/make.sh
# #
# (c)2006-2007, Laurence Withers, <l@lwithers.me.uk>. # (c)2009, Laurence Withers, <l@lwithers.me.uk>.
# Released under the GNU GPLv3. See file COPYING or # Released under the GNU GPLv3. See file COPYING or
# http://www.gnu.org/copyleft/gpl.html for details. # http://www.gnu.org/copyleft/gpl.html for details.
# #
@ -15,19 +15,19 @@ then
echo "Configuration file not found???" echo "Configuration file not found???"
exit 1 exit 1
fi fi
source "config" # don't fail on error, since last command in config might return false source "./config" # don't fail on error, since last command in config might return false
# Get version information # Get version information
source version || exit 1 source "./version" || exit 1
VERSION="${VERMAJOR}.${VERMINOR}.${VERMICRO}" VERSION="${VERMAJOR}.${VERMINOR}.${VERMICRO}"
# Get standard functions # Get standard functions
[ -z "${VERBOSE}" ] && VERBOSE="0" [ -z "${VERBOSE}" ] && VERBOSE="0"
source scripts/functions.sh || exit 1 source "./scripts/functions.sh" || exit 1
# List of directories which will be emptied by clean. # List of directories which will be emptied by clean.
@ -292,5 +292,4 @@ done
exit 0 exit 0
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: expandtab:ts=4:sw=4 # vim: expandtab:ts=4:sw=4

View File

@ -1,9 +1,9 @@
#!/bin/sh #!/bin/bash
# libiso8601/test.sh # libiso8601/test.sh
# #
# (c)2007, Laurence Withers, <l@lwithers.me.uk>. # Copyright: ©20092011, Güralp Systems Ltd.
# Released under the GNU GPLv3. See file COPYING or # Author: Laurence Withers <lwithers@guralp.com>
# http://www.gnu.org/copyleft/gpl.html for details. # License: GPLv3
# #
# Running this script on its own will display a summary of all the # Running this script on its own will display a summary of all the
@ -21,7 +21,7 @@ run_test() {
return 1 return 1
fi fi
LD_LIBRARY_PATH="obj" "${EXE}" "$@" || return 1 LD_LIBRARY_PATH="obj:${LD_LIBRARY_PATH}" "${EXE}" "$@" || return 1
return 0 return 0
} }
@ -33,14 +33,15 @@ print_tests() {
echo "---------------------------------------------------------------------" echo "---------------------------------------------------------------------"
for EXE in obj/tests/* for EXE in obj/tests/*
do do
[ -x ${EXE} ] || continue [ -x "${EXE}" ] || continue
NAME=$(echo ${EXE} | sed 's,obj/tests/,,') NAME="$(echo "${EXE}" | sed 's,obj/tests/,,')"
echo -ne "${NAME}\t" echo -ne "${NAME}\t"
LD_LIBRARY_PATH="obj" ${EXE} --print-summary LD_LIBRARY_PATH="obj:${LD_LIBRARY_PATH}" "${EXE}" --print-summary
done done
} }
# Main script # Main script
if [ $# -eq 0 ] if [ $# -eq 0 ]
then then
@ -48,7 +49,6 @@ then
exit 0 exit 0
fi fi
run_test $* run_test "$@"
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: expandtab:ts=4:sw=4 # vim: expandtab:ts=4:sw=4

1
scripts/.gitignore vendored
View File

@ -7,6 +7,7 @@ build.docs.none
build.files.none build.files.none
build.firmware.gpasm build.firmware.gpasm
build.firmware.sdcc build.firmware.sdcc
build.header.c
build.lib.c build.lib.c
build.lib.c++ build.lib.c++
build.make.none build.make.none

View File

@ -1,8 +1,8 @@
# libiso8601/scripts/functions.sh # libiso8601/scripts/functions.sh
# #
# (c)2007, Laurence Withers, <l@lwithers.me.uk>. # Copyright: ©20072011, Güralp Systems Ltd.
# Released under the GNU GPLv3. See file COPYING or # Author: Laurence Withers, <lwithers@guralp.com>
# http://www.gnu.org/copyleft/gpl.html for details. # License: GPLv3
# #
# Common functions # Common functions
@ -63,5 +63,4 @@ do_cmd_redir() {
fi fi
} }
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: expandtab:ts=4:sw=4 # vim: expandtab:ts=4:sw=4

View File

@ -1,8 +1,8 @@
# libiso8601/scripts/paths # libiso8601/scripts/paths
# #
# (c)2007, Laurence Withers, <l@lwithers.me.uk>. # Copyright: ©2011, Güralp Systems Ltd.
# Released under the GNU GPLv3. See file COPYING or # Author: Laurence Withers, <lwithers@guralp.com>
# http://www.gnu.org/copyleft/gpl.html for details. # License: GPLv3
# #
# Default path setup. Not meant for editing; use environment variables # Default path setup. Not meant for editing; use environment variables
# to override values if needed. # to override values if needed.
@ -60,5 +60,4 @@ fi
[ -z "${WEBDIR}" ] && WEBDIR="${SRVDIR}/http" [ -z "${WEBDIR}" ] && WEBDIR="${SRVDIR}/http"
[ -z "${CGIDIR}" ] && CGIDIR="${WEBDIR}/cgi-bin" [ -z "${CGIDIR}" ] && CGIDIR="${WEBDIR}/cgi-bin"
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: syntax=sh:expandtab:ts=4:sw=4 # vim: syntax=sh:expandtab:ts=4:sw=4

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,16 @@
/* libiso8601/src/docs/MainPage.dox /* libiso8601/src/docs/MainPage.dox
* *
* (c)2007, Laurence Withers, <l@lwithers.me.uk>. * (c)2007-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv3. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
/*! \mainpage /*! \mainpage Library for manipulating ISO8601-format dates and times
\c libiso8601 is a library containing conversion routines for ISO8601-format
dates and times and a set of associated date/time manipulation routines. It has
support for leap seconds and nanosecond accuracy and is intended for use in
e.g. physical science applications.
*/ */

View File

@ -39,5 +39,4 @@ then
docs_BUILT=1 docs_BUILT=1
fi fi
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: syntax=sh:expandtab:ts=4:sw=4 # vim: syntax=sh:expandtab:ts=4:sw=4

View File

@ -17,5 +17,4 @@ do
done done
print_success "Documentation installed" print_success "Documentation installed"
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: syntax=sh:expandtab:ts=4:sw=4 # vim: syntax=sh:expandtab:ts=4:sw=4

View File

@ -8,7 +8,8 @@ build_target libiso8601
if [ -z ${isodate_BUILT} ] if [ -z ${isodate_BUILT} ]
then then
isodate="obj/isodate" isodate="obj/isodate"
EXTRAS="${libiso8601} ${libiso8601_DEP_CFLAGS} ${libiso8601_DEP_LIBS}" EXTRAS="-std=gnu99 -D_GNU_SOURCE -DAPP_NAME=\"isodate\" \
${libiso8601} ${libiso8601_DEP_CFLAGS} ${libiso8601_DEP_LIBS}"
echo "Building application ${isodate}..." echo "Building application ${isodate}..."
@ -39,5 +40,4 @@ then
fi fi
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: syntax=sh:expandtab:ts=4:sw=4 # vim: syntax=sh:expandtab:ts=4:sw=4

View File

@ -8,5 +8,4 @@ echo "Installing binaries into '${BINDIR}'"
install_file "${isodate}" "${BINDIR}" 0755 || return 1 install_file "${isodate}" "${BINDIR}" 0755 || return 1
print_success "Done" print_success "Done"
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: syntax=sh:expandtab:ts=4:sw=4 # vim: syntax=sh:expandtab:ts=4:sw=4

View File

@ -14,5 +14,4 @@ then
MONOLITHIC_DOC="${MONOLITHIC_DOC} ${SRC}" MONOLITHIC_DOC="${MONOLITHIC_DOC} ${SRC}"
fi fi
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: syntax=sh:expandtab:ts=4:sw=4 # vim: syntax=sh:expandtab:ts=4:sw=4

View File

@ -1,13 +1,17 @@
/* libiso8601/src/libiso8601/000_TopHeader.h /* libiso8601/src/libiso8601/000_TopHeader.h
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
#ifndef HEADER_libiso8601 #ifndef HEADER_libiso8601
#define HEADER_libiso8601 #define HEADER_libiso8601
#ifdef __cplusplus
extern "C" {
#endif
/* standard includes, or includes needed for type declarations */ /* standard includes, or includes needed for type declarations */
#include <time.h> #include <time.h>
#include <stdint.h> #include <stdint.h>

View File

@ -1,7 +1,7 @@
/* libiso8601/src/libiso8601/000_TopSource.c /* libiso8601/src/libiso8601/000_TopSource.c
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */

View File

@ -1,25 +1,28 @@
/* libiso8601/src/libiso8601/100_calc.c /* libiso8601/src/libiso8601/100_calc.c
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
/* CALCULATION ROUTINES /* CALCULATION ROUTINES ********************************************************
*
* This file contains calculation routines used internally in the library. Our date format is the This file contains calculation routines used internally in the library. Our
* number of days elapsed since 0000-001 (so that date would be 0, -0001-365 would be -1, etc.). date format is the number of days elapsed since 0000-001 (so that date would be
* Time is represented as the number of seconds elapsed since midnight at the start of the day. It 0, -0001-365 would be -1, etc.). Time is represented as the number of seconds
* is a value between 0 and 86399 (or 86400 for leap seconds). elapsed since midnight at the start of the day. It is a value between 0 and
*/ 86399 (or 86400 for leap seconds).
*******************************************************************************/
#define DAYS_IN_400_YEARS (146097) #define DAYS_IN_400_YEARS (146097)
int iso8601_isleap(int year) int
iso8601_isleap(int year)
{ {
if(year % 4) return 0; if(year % 4) return 0;
if(year % 100) return 1; if(year % 100) return 1;
@ -31,14 +34,15 @@ int iso8601_isleap(int year)
/* struct monthcount, _days_in_month_common[], _days_in_month_leap[] /* struct monthcount, _days_in_month_common[], _days_in_month_leap[]
* *
* Tables of the number of days in each month, and the number of days elapsed since the start of * Tables of the number of days in each month, and the number of days elapsed
* the year for each month. * since the start of the year for each month.
*/ */
struct monthcount { struct monthcount {
int elapsed, days; int elapsed, days;
}; };
static const struct monthcount _days_in_month_common[] = { static const struct monthcount
_days_in_month_common[] = {
{ 0, 31 }, { 0, 31 },
{ 31, 28 }, { 31, 28 },
{ 59, 31 }, { 59, 31 },
@ -53,7 +57,8 @@ static const struct monthcount _days_in_month_common[] = {
{ 334, 31 } { 334, 31 }
}; };
static const struct monthcount _days_in_month_leap[] = { static const struct monthcount
_days_in_month_leap[] = {
{ 0, 31 }, { 0, 31 },
{ 31, 29 }, { 31, 29 },
{ 60, 31 }, { 60, 31 },
@ -70,7 +75,8 @@ static const struct monthcount _days_in_month_leap[] = {
static int _days_in_month(int year, int month) static int
_days_in_month(int year, int month)
{ {
const struct monthcount* mc; const struct monthcount* mc;
@ -85,42 +91,45 @@ static int _days_in_month(int year, int month)
static void _to_year(int* year, int* days_left, const struct iso8601_date* date) static void
_to_year(int* year, int* days_left, const struct iso8601_date* date)
{ {
div_t qr; div_t qr;
int ndays = date->day; int ndays = date->day;
// Each 400 years have 97 leap days, giving 365*400+97 = DAYS_IN_400_YEARS days in 400 years /* Each 400 years have 97 leap days, giving 365*400+97 = DAYS_IN_400_YEARS
days in 400 years */
qr = div(ndays, DAYS_IN_400_YEARS); qr = div(ndays, DAYS_IN_400_YEARS);
*year = qr.quot * 400; *year = qr.quot * 400;
ndays = qr.rem; ndays = qr.rem;
// ensure that we always end up with between 0 and 146096 days remaining /* ensure that we always end up with between 0 and 146096 days remaining */
if(ndays < 0) { if(ndays < 0) {
ndays += DAYS_IN_400_YEARS; ndays += DAYS_IN_400_YEARS;
*year -= 400; *year -= 400;
} }
// we insert `fake' leap days for years 101, 201, 301 /* we insert `fake' leap days for years 101, 201, 301 */
if(ndays >= 36890) ++ndays; if(ndays >= 36890) ++ndays;
if(ndays >= 73415) ++ndays; if(ndays >= 73415) ++ndays;
if(ndays >= 109940) ++ndays; if(ndays >= 109940) ++ndays;
// each remaining 100 year block has 24 leap days, giving 365*100+24 = 36524 days /* each remaining 100 year block has 24 leap days, giving 365*100+24 = 36524
days */
qr = div(ndays, 36525); qr = div(ndays, 36525);
*year += qr.quot * 100; *year += qr.quot * 100;
ndays = qr.rem; ndays = qr.rem;
// each 4-year block has 1 leap day, giving 365*4 + 1 = 1461 days /* each 4-year block has 1 leap day, giving 365*4 + 1 = 1461 days */
qr = div(ndays, 1461); qr = div(ndays, 1461);
*year += qr.quot * 4; *year += qr.quot * 4;
ndays = qr.rem; ndays = qr.rem;
// the first year of a 4-year block has 1 leap day, 366 days /* the first year of a 4-year block has 1 leap day, 366 days */
if(ndays >= 366) { if(ndays >= 366) {
--ndays; // pretend to have dealt with leap day --ndays; /* pretend to have dealt with leap day */
// 365 days per remaining year /* 365 days per remaining year */
qr = div(ndays, 365); qr = div(ndays, 365);
*year += qr.quot; *year += qr.quot;
ndays = qr.rem; ndays = qr.rem;
@ -131,15 +140,16 @@ static void _to_year(int* year, int* days_left, const struct iso8601_date* date)
void iso8601_to_cal(int* year, int* month, int* day, const struct iso8601_date* date) void
iso8601_to_cal(int* year, int* month, int* day, const struct iso8601_date* date)
{ {
const struct monthcount* mc; const struct monthcount* mc;
int ndays; int ndays;
// perform year calulation /* perform year calulation */
_to_year(year, &ndays, date); _to_year(year, &ndays, date);
// now we simply have number of days elapsed since day 001 in `year'. /* now we simply have number of days elapsed since day 001 in `year'. */
mc = iso8601_isleap(*year) ? _days_in_month_leap : _days_in_month_common; mc = iso8601_isleap(*year) ? _days_in_month_leap : _days_in_month_common;
*month = 1; *month = 1;
while(ndays >= mc->days) { while(ndays >= mc->days) {
@ -152,35 +162,38 @@ void iso8601_to_cal(int* year, int* month, int* day, const struct iso8601_date*
void iso8601_to_ord(int* year, int* oday, const struct iso8601_date* date) void
iso8601_to_ord(int* year, int* oday, const struct iso8601_date* date)
{ {
int ndays; int ndays;
// perform year calcutation /* perform year calcutation */
_to_year(year, &ndays, date); _to_year(year, &ndays, date);
// now we simply have number of days elapsed since day 001 in `year'. /* now we simply have number of days elapsed since day 001 in `year'. */
*oday = ndays + 1; *oday = ndays + 1;
} }
static int _weekday_of_year(int year) static int
_weekday_of_year(int year)
{ {
int w = 6; int w = 6;
/* Algorithm notes: /* Algorithm notes:
* - 0 = sun, 1 = mon, ..., 6 = sat * 0 = sun, 1 = mon, ..., 6 = sat
* - 0000-001 is a Saturday, day 6 * 0000-001 is a Saturday, day 6
* - every year we pass gives us one additional day (364 is divisible by 7) * every year we pass gives us one additional day (364 is divisible by 7)
* - but of course every leap year we pass gives us a further day * but of course every leap year we pass gives us a further day
* - so for every 400 years, we add 497 (400 common years, 97 leap years); 497 % 7 = 0 * so for every 400 years, we add 497 (400 common years, 97 leap years);
* 497 % 7 = 0
*/ */
year %= 400; year %= 400;
if(year < 0) year += 400; // end up with between 0-399 years left if(year < 0) year += 400; /* end up with between 0-399 years left */
w += year; // excluding leap years, we increase by 1 day a year w += year; /* excluding leap years, we increase by 1 day a year */
w += (year + 3) / 4; // there is one leap year for every four years w += (year + 3) / 4; /* there is one leap year for every four years */
w -= (year - 1) / 100; // but one less for every century over 0 w -= (year - 1) / 100; /* but one less for every century over 0 */
w %= 7; w %= 7;
return w; return w;
@ -188,42 +201,47 @@ static int _weekday_of_year(int year)
void iso8601_to_week(int* year, int* week, int* wday, const struct iso8601_date* date) void
iso8601_to_week(int* year, int* week, int* wday,
const struct iso8601_date* date)
{ {
int ndays, w, has53 = 0; int ndays, w, has53 = 0;
div_t d; div_t d;
// perform year and weekday calculation /* perform year and weekday calculation */
_to_year(year, &ndays, date); _to_year(year, &ndays, date);
w = _weekday_of_year(*year); w = _weekday_of_year(*year);
// find out what day jan 1 was; from there, we can find the ISO week and year number /* find out what day jan 1 was; from there, we can find the ISO week and
year number */
switch(w) { switch(w) {
case 4: // W01 starts XXXY-12-28 case 4: /* W01 starts XXXY-12-28 */
w += 7; w += 7;
has53 = 1; // years starting Thursday have 53 weeks has53 = 1; /* years starting Thursday have 53 weeks */
break; break;
case 5: // W01 starts XXXZ-01-03 case 5: /* W01 starts XXXZ-01-03 */
case 6: // W01 starts XXXZ-01-02 case 6: /* W01 starts XXXZ-01-02 */
break; break;
case 0: // W01 starts XXXZ-01-01 case 0: /* W01 starts XXXZ-01-01 */
case 1: // W01 starts XXXY-12-31 case 1: /* W01 starts XXXY-12-31 */
case 2: // W01 starts XXXY-12-30 case 2: /* W01 starts XXXY-12-30 */
w += 7; // for week calculation w += 7; /* for week calculation */
break; break;
case 3: // W01 starts XXXY-12-29 case 3: /* W01 starts XXXY-12-29 */
w += 7; w += 7;
if(iso8601_isleap(*year)) has53 = 1; // leap years starting Wednesday have 53 weeks if(iso8601_isleap(*year)) has53 = 1; /* leap years starting Wednesday
have 53 weeks */
} }
// now we simply add the number of days elapsed since the start of the year, and % 7 /* now we simply add the number of days elapsed since the start of the
year, and % 7 */
w += ndays; w += ndays;
d = div(w, 7); // w can never be 0 d = div(w, 7); /* w can never be 0 */
// do Sunday correction /* do Sunday correction */
if(!d.rem) { if(!d.rem) {
d.rem = 7; d.rem = 7;
--d.quot; --d.quot;
@ -256,54 +274,57 @@ void iso8601_to_week(int* year, int* week, int* wday, const struct iso8601_date*
int _from_year(struct iso8601_date* date, int year) static int
_from_year(struct iso8601_date* date, int year)
{ {
div_t qr; div_t qr;
// check for range errors /* check for range errors */
if(year < -5879609 || year > 5879609) { if(year < -5879609 || year > 5879609) {
errno = ERANGE; errno = ERANGE;
return -1; return -1;
} }
// Each 400 years have 97 leap days, giving 365*400+97 = DAYS_IN_400_YEARS days in 400 years /* Each 400 years have 97 leap days, giving 365*400+97 = DAYS_IN_400_YEARS
days in 400 years */
qr = div(year, 400); qr = div(year, 400);
date->day = qr.quot * DAYS_IN_400_YEARS; date->day = qr.quot * DAYS_IN_400_YEARS;
year = qr.rem; year = qr.rem;
// ensure we have between 0 and 399 years /* ensure we have between 0 and 399 years */
if(year < 0) { if(year < 0) {
date->day -= DAYS_IN_400_YEARS; date->day -= DAYS_IN_400_YEARS;
year += 400; year += 400;
} }
// excluding leap days, there are 365 days per year /* excluding leap days, there are 365 days per year */
date->day += 365 * year; date->day += 365 * year;
date->day += (year + 3) / 4; // there is one leap year for every four years date->day += (year + 3) / 4; /* one leap year for every four years */
date->day -= (year - 1) / 100; // but one less for every century over 0 date->day -= (year - 1) / 100; /* but one less for every century over 0 */
return 0; return 0;
} }
int iso8601_from_cal(struct iso8601_date* date, int year, int month, int day) int
iso8601_from_cal(struct iso8601_date* date, int year, int month, int day)
{ {
const struct monthcount* mc; const struct monthcount* mc;
// check for domain errors /* check for domain errors */
mc = iso8601_isleap(year) ? _days_in_month_leap : _days_in_month_common; mc = iso8601_isleap(year) ? _days_in_month_leap : _days_in_month_common;
if(month < 1 || month > 12 || day < 1 || day > mc[month - 1].days) { if(month < 1 || month > 12 || day < 1 || day > mc[month - 1].days) {
errno = EDOM; errno = EDOM;
return -1; return -1;
} }
// perform year calculation /* perform year calculation */
if(_from_year(date, year)) return -1; if(_from_year(date, year)) return -1;
// now get number of days elapsed up to start of month /* now get number of days elapsed up to start of month */
date->day += mc[month - 1].elapsed; date->day += mc[month - 1].elapsed;
// and add number of days elapsed sinced start of month /* and add number of days elapsed sinced start of month */
date->day += day - 1; date->day += day - 1;
return 0; return 0;
@ -311,18 +332,19 @@ int iso8601_from_cal(struct iso8601_date* date, int year, int month, int day)
int iso8601_from_ord(struct iso8601_date* date, int year, int oday) int
iso8601_from_ord(struct iso8601_date* date, int year, int oday)
{ {
// check for domain errors /* check for domain errors */
if(oday < 1 || oday > (iso8601_isleap(year) ? 366 : 365)) { if(oday < 1 || oday > (iso8601_isleap(year) ? 366 : 365)) {
errno = EDOM; errno = EDOM;
return -1; return -1;
} }
// perform year calculation /* perform year calculation */
if(_from_year(date, year)) return -1; if(_from_year(date, year)) return -1;
// now simply add number of days elapsed this year /* now simply add number of days elapsed this year */
date->day += oday - 1; date->day += oday - 1;
return 0; return 0;
@ -330,18 +352,19 @@ int iso8601_from_ord(struct iso8601_date* date, int year, int oday)
int iso8601_from_week(struct iso8601_date* date, int isoyear, int week, int wday) int
iso8601_from_week(struct iso8601_date* date, int isoyear, int week, int wday)
{ {
int day1off, maxwk; int day1off, maxwk;
// compute year part /* compute year part */
_from_year(date, isoyear); _from_year(date, isoyear);
// 400-year cycle; ensure we're between 0-400 years /* 400-year cycle; ensure we're between 0-400 years */
isoyear %= 400; isoyear %= 400;
if(isoyear < 0) isoyear += 400; if(isoyear < 0) isoyear += 400;
// domain check /* domain check */
maxwk = (((isoyear % 7) == 52) || ((isoyear % 28) == 24)) ? 53 : 52; maxwk = (((isoyear % 7) == 52) || ((isoyear % 28) == 24)) ? 53 : 52;
if(wday < 1 || wday > 7 || week < 1 || week > maxwk) { if(wday < 1 || wday > 7 || week < 1 || week > maxwk) {
errno = EDOM; errno = EDOM;
@ -349,18 +372,20 @@ int iso8601_from_week(struct iso8601_date* date, int isoyear, int week, int wday
} }
/* Algorithm notes: /* Algorithm notes:
* We now compute the offset between the start day of the ISO year and the start day of the * We now compute the offset between the start day of the ISO year and
* real year. Year 0000 starts on a Saturday, meaning the ISO year 0000 starts on 0000-003 * the start day of the real year. Year 0000 starts on a Saturday, meaning
* (offset of +2 days). Each year reduces the offset by one day, and each leap year reduces it * the ISO year 0000 starts on 0000-003 (offset of +2 days). Each year
* by a further day; the offset wraps from -3 to +3. * reduces the offset by one day, and each leap year reduces it by a
* further day; the offset wraps from -3 to +3.
*/ */
day1off = 2 - isoyear; // reduce offset by 1 for each year day1off = 2 - isoyear; /* reduce offset by 1 for each year */
day1off += (isoyear - 1) / 100; // cancel out 1 leap year for each century past the first day1off += (isoyear - 1) / 100; /* cancel out 1 leap year for each century
day1off -= (isoyear + 3) / 4; // 1 leap year every 4 years past the first */
day1off -= (isoyear + 3) / 4; /* 1 leap year every 4 years */
day1off %= 7; day1off %= 7;
if(day1off < -3) day1off += 7; if(day1off < -3) day1off += 7;
// now simply add in the day offset and days/weeks elapsed /* now simply add in the day offset and days/weeks elapsed */
date->day += day1off + (week - 1) * 7 + wday - 1; date->day += day1off + (week - 1) * 7 + wday - 1;
return 0; return 0;
@ -368,11 +393,13 @@ int iso8601_from_week(struct iso8601_date* date, int isoyear, int week, int wday
void iso8601_to_clocktime(int* hour, int* min, int* sec, const struct iso8601_date* date) void
iso8601_to_clocktime(int* hour, int* min, int* sec,
const struct iso8601_date* date)
{ {
div_t qr; div_t qr;
// special case: leap second /* special case: leap second */
if(date->sec == 86400) { if(date->sec == 86400) {
*hour = 23; *hour = 23;
*min = 59; *min = 59;
@ -380,7 +407,7 @@ void iso8601_to_clocktime(int* hour, int* min, int* sec, const struct iso8601_da
return; return;
} }
// normal case /* normal case */
qr = div(date->sec, 3600); qr = div(date->sec, 3600);
*hour = qr.quot; *hour = qr.quot;
qr = div(qr.rem, 60); qr = div(qr.rem, 60);
@ -390,21 +417,22 @@ void iso8601_to_clocktime(int* hour, int* min, int* sec, const struct iso8601_da
int iso8601_from_clocktime(struct iso8601_date* date, int hour, int min, int sec) int
iso8601_from_clocktime(struct iso8601_date* date, int hour, int min, int sec)
{ {
// special case: leap second /* special case: leap second */
if(hour == 23 && min == 59 && sec == 60) { if(hour == 23 && min == 59 && sec == 60) {
date->sec = 86400; date->sec = 86400;
return 0; return 0;
} }
// domain check /* domain check */
if(hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 59) { if(hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 59) {
errno = EDOM; errno = EDOM;
return -1; return -1;
} }
// normal calculation /* normal calculation */
date->sec = hour * 3600 + min * 60 + sec; date->sec = hour * 3600 + min * 60 + sec;
return 0; return 0;
} }

View File

@ -1,13 +1,20 @@
/* libiso8601/src/libiso8601/100_leap.c /* libiso8601/src/libiso8601/100_leap.c
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
static int leap_second_days_table[] = { /* leap_second_days_table[]
* This is a sorted array of days (in libiso8601 format) on which a positive
* leap second occurred. This table is built in to the library, but may be
* overridden at runtime by changing what leap_second_days points to. There
* should be no other references to this table, therefore.
*/
static int
leap_second_days_table[] = {
720439, /* 1972-06-30 */ 720439, /* 1972-06-30 */
720623, /* 1972-12-31 */ 720623, /* 1972-12-31 */
720988, /* 1973-12-31 */ 720988, /* 1973-12-31 */
@ -32,25 +39,47 @@ static int leap_second_days_table[] = {
730119, /* 1998-12-31 */ 730119, /* 1998-12-31 */
732676, /* 2005-12-31 */ 732676, /* 2005-12-31 */
733772, /* 2008-12-31 */ 733772, /* 2008-12-31 */
735049, /* 2012-06-30 */
736144, /* 2015-06-30 */
}; };
static int* leap_second_days = leap_second_days_table; /* leap_second_days[], leap_second_days_num
static int leap_second_days_num = sizeof(leap_second_days_table) / sizeof(int); * Pointer to an array (and number of elements in the array) representing the
* table of positive leap seconds. The array is sorted and contains libiso8601
* day numbers of days with positive leap seconds.
*/
static int*
leap_second_days = leap_second_days_table;
static int
leap_second_days_num = sizeof(leap_second_days_table) / sizeof(int);
int iso8601_seconds_leap(const struct iso8601_date* date) /* iso8601_seconds_leap()
* Returns the number of seconds that elapse on a given date, which requires us
* to search the table of leap seconds to see if we need to return a special
* case.
*/
int
iso8601_seconds_leap(const struct iso8601_date* date)
{ {
int i; int i;
for(i = 0; i < leap_second_days_num; ++i) if(leap_second_days[i] == date->day) return 86401; for(i = 0; i < leap_second_days_num; ++i) {
if(leap_second_days[i] == date->day) return 86401;
}
return 86400; return 86400;
} }
static int _leap_elapsed_day(int sday, int eday) /* _leap_elapsed_day()
* Returns the number of leap seconds that have elapsed between sday (start
* day) and eday (end day), both in libiso8601 format.
*/
static int
_leap_elapsed_day(int sday, int eday)
{ {
int spos, epos; int spos, epos;
@ -66,16 +95,31 @@ static int _leap_elapsed_day(int sday, int eday)
int iso8601_leap_elapsed(const struct iso8601_date* start, const struct iso8601_date* end) /* iso8601_leap_elapsed()
* Wrapper around _leap_elapsed_day().
*/
int
iso8601_leap_elapsed(const struct iso8601_date* start,
const struct iso8601_date* end)
{ {
return _leap_elapsed_day(start->day, end->day); return _leap_elapsed_day(start->day, end->day);
} }
/* leap_table_free_old
* If set, then when we update the leap table, we should free the old array.
* Initially clear so that we don't free our static built-in table.
*/
static int leap_table_free_old = 0; static int leap_table_free_old = 0;
void iso8601_leap_table_set(int* new_table, int new_size)
/* iso8601_leap_table_set()
* Switch to using a new table of leap seconds, possibly freeing the old one.
*/
void
iso8601_leap_table_set(int* new_table, int new_size)
{ {
if(leap_table_free_old) free(leap_second_days); if(leap_table_free_old) free(leap_second_days);
leap_table_free_old = 0; leap_table_free_old = 0;
@ -86,16 +130,29 @@ void iso8601_leap_table_set(int* new_table, int new_size)
static const char* leap_table_signature = "/O9PdPZI"; /* leap_table_signature
* The first 8 bytes of a leap second table must match this string, otherwise
* the file is taken not to be of the correct format.
*/
static const char*
leap_table_signature = "/O9PdPZI";
int iso8601_leap_table_load(const char* fname) /* iso8601_leap_table_load()
* Loads a new table of leap seconds from disk. Ensures the signature of the
* given file matches leap_table_signature, and does some basic sanity
* checking (file in sorted order etc.).
*/
int
iso8601_leap_table_load(const char* fname)
{ {
struct stat st; struct stat st;
int fd, saved_errno, i, new_size, * days = 0; int fd, saved_errno, i, new_size, * days = 0;
char buf[12]; char buf[12];
if(!fname) fname = DEFAULT_LEAP_TABLE;
if(stat(fname, &st)) return -1; if(stat(fname, &st)) return -1;
if(st.st_size < 12) { if(st.st_size < 12) {
errno = EINVAL; errno = EINVAL;

View File

@ -1,7 +1,7 @@
/* libiso8601/src/libiso8601/100_types.h /* libiso8601/src/libiso8601/100_types.h
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
@ -9,19 +9,20 @@
/*! \brief Date/time point. /*! \brief Date/time point.
This structure contains the details to represent a specific instant on the UTC timescale. It uses This structure contains the details to represent a specific instant on the UTC
Jan 1, year 0000 as the origin (when \a day will be 0). \a sec is the number of seconds elapsed timescale. It uses Jan 1, year 0000 as the origin (when \a day will be 0). \a
since start of day, and \a nsec is the number of nanoseconds elapsed since the start of the current sec is the number of seconds elapsed since start of day, and \a nsec is the
second. number of nanoseconds elapsed since the start of the current second.
We correctly deal with leap seconds by encoding 23:59:60 as having a \a sec field of 86400. We correctly deal with leap seconds by encoding 23:59:60 as having a \a sec
field of 86400.
*/ */
struct iso8601_date { struct iso8601_date {
/*! \brief Number of nanoseconds elapsed since start of second. */ /*! \brief Number of nanoseconds elapsed since start of second. */
int32_t nsec; int32_t nsec;
/*! \brief Number of days elapsed since Jan 1, year 0000. May be negative. */ /*! \brief Number of days elapsed since Jan 1, year 0000. May be negative.*/
int32_t day; int32_t day;
/*! \brief Number of seconds elapsed since start of day. */ /*! \brief Number of seconds elapsed since start of day. */
@ -33,9 +34,10 @@ struct iso8601_date {
/*! \brief Date (day portion) precision. /*! \brief Date (day portion) precision.
\ingroup parser \ingroup parser
This enumeration will record how precisely the date was specified, as well as the format in use. It This enumeration will record how precisely the date was specified, as well as
allows the library to determine the earliest and latest dates that could possibly be represented the format in use. It allows the library to determine the earliest and latest
with the given input and also allows the output format to match the input format. dates that could possibly be represented with the given input and also allows
the output format to match the input format.
*/ */
enum iso8601_date_prec { enum iso8601_date_prec {
@ -56,16 +58,17 @@ enum iso8601_date_prec {
/*! \brief Year, week and weekday specified (week format). */ /*! \brief Year, week and weekday specified (week format). */
iso8601_prec_wday iso8601_prec_wday
}date_prec; };
/*! \brief Time precision. /*! \brief Time precision.
\ingroup parser \ingroup parser
This enumeration records how precisely the time was specified as well as its format. The fractional This enumeration records how precisely the time was specified as well as its
format will record whether it was the hour, minute or second that was specified with a fractional format. The fractional format will record whether it was the hour, minute or
part, allowing a processed date/time to be presented to the user in the format it was originally second that was specified with a fractional part, allowing a processed
date/time to be presented to the user in the format it was originally
encountered. encountered.
*/ */
@ -84,16 +87,16 @@ enum iso8601_time_prec {
iso8601_prec_minfrac, iso8601_prec_minfrac,
/*! \brief Display hour, minute, second and nanoseconds. */ /*! \brief Display hour, minute, second and nanoseconds. */
iso8601_prec_secfrac iso8601_prec_secfrac
}time_prec; };
/*! \brief Date/time formatting details. /*! \brief Date/time formatting details.
This structure simply records details related to the formatting (and precision) of a date/time This structure simply records details related to the formatting (and precision)
structure. The structure can be filled out by the parser so that a program's output can match of a date/time structure. The structure can be filled out by the parser so that
the format of its input. Alternatively it can be controlled by the program to provide a consistent a program's output can match the format of its input. Alternatively it can be
output format. controlled by the program to provide a consistent output format.
*/ */
struct iso8601_details { struct iso8601_details {
@ -114,9 +117,10 @@ struct iso8601_details {
/*! \brief Short period elapsed time. /*! \brief Short period elapsed time.
This structure contains the details of an elapsed time period, split into seconds and nanoseconds. This structure contains the details of an elapsed time period, split into
None of its components can ever be negative. This is only capable of representing short (compared to seconds and nanoseconds. None of its components can ever be negative. This is
struct iso8601_date's range) periods of up to approximately 136 years. only capable of representing short (compared to struct iso8601_date's range)
periods of up to approximately 136 years.
*/ */
struct iso8601_elapsed { struct iso8601_elapsed {

View File

@ -1,24 +1,25 @@
/* libiso8601/src/libiso8601/200_parser.c /* libiso8601/src/libiso8601/200_parser.c
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
int iso8601_parse(const char* str, struct iso8601_date* earliest, struct iso8601_date* latest, int
struct iso8601_details* details) iso8601_parse(const char* str, struct iso8601_date* earliest,
struct iso8601_date* latest, struct iso8601_details* details)
{ {
enum { enum {
state_none, state_none,
state_year, // e.g. `2006' or `2006123' state_year, /* e.g. `2006' or `2006123' */
state_date2, // 2nd component of date, e.g. `2006-' or `2006-1' state_date2, /* 2nd component of date, e.g. `2006-' or `2006-1' */
state_day, // e.g. `2006-01-' or `2006-01-01' state_day, /* e.g. `2006-01-' or `2006-01-01' */
state_week_basic, // e.g. `2006W' or `2006W123' state_week_basic, /* e.g. `2006W' or `2006W123' */
state_week_extended, // e.g. `2006-W' or `2006-W31' state_week_extended, /* e.g. `2006-W' or `2006-W31' */
state_week_day, // e.g. `2006-W31-' state_week_day, /* e.g. `2006-W31-' */
state_week_done, // `2006-W31-1' state_week_done, /* `2006-W31-1' */
state_time_basic, state_time_basic,
state_time_hour, state_time_hour,
state_time_min, state_time_min,
@ -34,8 +35,9 @@ int iso8601_parse(const char* str, struct iso8601_date* earliest, struct iso8601
div_t qr; div_t qr;
char ch; char ch;
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,
int y = 0, m = -1, d = -1, w = -1, wd = -1, hour = -1, min = -1, sec = -1, tz_sec = 0; leap_sec_req = 0, 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; struct iso8601_elapsed elapsed;
@ -436,7 +438,8 @@ int iso8601_parse(const char* str, struct iso8601_date* earliest, struct iso8601
case '-': case '-':
tz_neg = -1; tz_neg = -1;
case '+': case '+':
state = (state == state_time_nsec_basic) ? state_tz_basic : state_tz_hour; state = (state == state_time_nsec_basic) ?
state_tz_basic : state_tz_hour;
break; break;
} }
break; break;
@ -544,7 +547,8 @@ done:
if(m != -1) { if(m != -1) {
if(d == -1) { if(d == -1) {
ERROR_IF(earliest && iso8601_from_cal(earliest, y, m, 1)); ERROR_IF(earliest && iso8601_from_cal(earliest, y, m, 1));
ERROR_IF(latest && iso8601_from_cal(latest, y, m, _days_in_month(y, m))); ERROR_IF(latest && iso8601_from_cal(latest, y, m,
_days_in_month(y, m)));
if(details) details->date_prec = iso8601_prec_month; if(details) details->date_prec = iso8601_prec_month;
} else { } else {
@ -608,7 +612,8 @@ done:
} else if(min != -1) { } else if(min != -1) {
if(nsec_dig == -1) { if(nsec_dig == -1) {
ERROR_IF(earliest && iso8601_from_clocktime(earliest, hour, min, 0)); ERROR_IF(earliest && iso8601_from_clocktime(earliest,
hour, min, 0));
ERROR_IF(latest && iso8601_from_clocktime(latest, hour, min, 59)); ERROR_IF(latest && iso8601_from_clocktime(latest, hour, min, 59));
if(latest) latest->nsec = 999999999; if(latest) latest->nsec = 999999999;
if(details) details->time_prec = iso8601_prec_min; if(details) details->time_prec = iso8601_prec_min;
@ -617,7 +622,8 @@ done:
frac = nsec * 60.0 / 1e9; frac = nsec * 60.0 / 1e9;
sec = (int)frac; sec = (int)frac;
nsec = (frac - sec) * 1e9; nsec = (frac - sec) * 1e9;
ERROR_IF(earliest && iso8601_from_clocktime(earliest, hour, min, sec)); ERROR_IF(earliest && iso8601_from_clocktime(earliest,
hour, min, sec));
if(earliest) earliest->nsec = nsec; if(earliest) earliest->nsec = nsec;
ERROR_IF(latest && iso8601_from_clocktime(latest, hour, min, sec)); ERROR_IF(latest && iso8601_from_clocktime(latest, hour, min, sec));
if(latest) latest->nsec = nsec; if(latest) latest->nsec = nsec;
@ -639,7 +645,8 @@ done:
frac *= 60; frac *= 60;
sec = (int)frac; sec = (int)frac;
nsec = (frac - sec) * 1e9; nsec = (frac - sec) * 1e9;
ERROR_IF(earliest && iso8601_from_clocktime(earliest, hour, min, sec)); ERROR_IF(earliest && iso8601_from_clocktime(earliest,
hour, min, sec));
if(earliest) earliest->nsec = nsec; if(earliest) earliest->nsec = nsec;
ERROR_IF(latest && iso8601_from_clocktime(latest, hour, min, sec)); ERROR_IF(latest && iso8601_from_clocktime(latest, hour, min, sec));
if(latest) latest->nsec = nsec; if(latest) latest->nsec = nsec;
@ -676,7 +683,8 @@ done:
int iso8601_invalid(const struct iso8601_date* date) int
iso8601_invalid(const struct iso8601_date* date)
{ {
return date->nsec < 0 return date->nsec < 0
|| date->nsec >= BILLION || date->nsec >= BILLION

View File

@ -1,7 +1,7 @@
/* libiso8601/src/libiso8601/200_parser.h /* libiso8601/src/libiso8601/200_parser.h
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
@ -9,31 +9,41 @@
/*! \defgroup parser Parsing, printing and validation routines. /*! \defgroup parser Parsing, printing and validation routines.
These routines are used for parsing an ISO8601 date/time string into the internal structure used These routines are used for parsing an ISO8601 date/time string into the
to represent them, and for validating such dates/times. internal structure used to represent them, and for validating such dates/times.
*/ */
/*!@{*/ /*!@{*/
/*! \brief Parse ISO8601 date/time. /*! \brief Parse ISO8601 date/time.
\param str The input string. Whitespace will be stripped. \param str The input string. Whitespace will be stripped.
\param[out] earliest The earliest possible time the string could represent. May be 0. \param[out] earliest The earliest possible time the string could represent. May
\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. be 0.
\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. \retval -1 on error.
\retval 0 on success. \retval 0 on success.
Parses a string containing the ISO8601 date/time. Deals with any format of date, optionally storing Parses a string containing the ISO8601 date/time. Deals with any format of
the details in \a details. The time may be partial, in which case this function returns the earliest date, optionally storing the details in \a details. The time may be partial, in
and latest times that could possibly be represented by the string. 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. Note that this function will accept leap seconds (23:59:60) on days on which
they occurred.
*/ */
int iso8601_parse(const char* str, struct iso8601_date* earliest, struct iso8601_date* latest, int iso8601_parse(const char* str, struct iso8601_date* earliest,
struct iso8601_details* details); struct iso8601_date* latest, struct iso8601_details* details)
#ifndef DOXYGEN
__attribute__((nonnull(1),warn_unused_result))
#endif
;
@ -45,12 +55,17 @@ int iso8601_parse(const char* str, struct iso8601_date* earliest, struct iso8601
\param details Formatting details (may be 0). \param details Formatting details (may be 0).
\returns Pointer to buffer (\a str). \returns Pointer to buffer (\a str).
Formats and prints an ISO8601 date, optionally using the details in \a details. Will always return Formats and prints an ISO8601 date, optionally using the details in \a details.
a null-terminated result, even if that means truncating the output to fit the buffer. Will always return a null-terminated result, even if that means truncating the
output to fit the buffer.
*/ */
char* iso8601_print(char* str, int amt, const struct iso8601_date* date, char* iso8601_print(char* str, int amt, const struct iso8601_date* date,
const struct iso8601_details* details); const struct iso8601_details* details)
#ifndef DOXYGEN
__attribute__((nonnull(1,3)))
#endif
;
@ -60,18 +75,21 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date,
\retval -1 if not valid. \retval -1 if not valid.
\retval 0 if valid. \retval 0 if valid.
Checks the details of \a date to ensure that they are sensible. This involves checking that \a sec Checks the details of \a date to ensure that they are sensible. This involves
is in the range 0 to 86399 (or 86400 if there is a leap second), and that \a nsec is in the range 0 checking that \a sec is in the range 0 to 86399 (or 86400 if there is a leap
to 999999999. second), and that \a nsec is in the range 0 to 999999999.
*/ */
int iso8601_invalid(const struct iso8601_date* date); int iso8601_invalid(const struct iso8601_date* date)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
/*!@}*/ /*!@}*/
/* 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:syntax=ch.doxygen
*/ */

View File

@ -1,13 +1,18 @@
/* libiso8601/src/libiso8601/print.c /* libiso8601/src/libiso8601/200_print.c
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
static const struct iso8601_details _default_details = { /* _default_details
* If the user doesn't pass precision details to iso8601_print(), these are
* used instead.
*/
static const struct iso8601_details
_default_details = {
iso8601_prec_day, iso8601_prec_day,
iso8601_prec_sec, iso8601_prec_sec,
1, 1,
@ -16,7 +21,8 @@ static const struct iso8601_details _default_details = {
char* iso8601_print(char* str, int amt, const struct iso8601_date* date, char*
iso8601_print(char* str, int amt, const struct iso8601_date* date,
const struct iso8601_details* details) const struct iso8601_details* details)
{ {
int y, m, d, ret = 0, extended; int y, m, d, ret = 0, extended;
@ -27,10 +33,10 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date,
str_orig = str; str_orig = str;
// use default details if none provided /* use default details if none provided */
if(!details) details = &_default_details; if(!details) details = &_default_details;
// adjust output for timezone /* adjust output for timezone */
dttz = *date; dttz = *date;
if(details->tz_sec) { if(details->tz_sec) {
elapsed.sec = details ? details->tz_sec : 0; elapsed.sec = details ? details->tz_sec : 0;
@ -38,7 +44,7 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date,
iso8601_add_elapsed(&dttz, &elapsed); 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);
extended = details->extended || y < 0 || y > 9999; extended = details->extended || y < 0 || y > 9999;
@ -55,27 +61,32 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date,
case iso8601_prec_day: case iso8601_prec_day:
if(y < 0) ret = snprintf(str, amt, "%05d-%02d-%02d", y, m, d); if(y < 0) ret = snprintf(str, amt, "%05d-%02d-%02d", y, m, d);
else ret = snprintf(str, amt, extended ? "%04d-%02d-%02d" : "%04d%02d%02d", y, m, d); else ret = snprintf(str, amt, extended ?
"%04d-%02d-%02d" : "%04d%02d%02d", y, m, d);
break; break;
case iso8601_prec_ord: case iso8601_prec_ord:
iso8601_to_ord(&y, &d, &dttz); iso8601_to_ord(&y, &d, &dttz);
if(y < 0) ret = snprintf(str, amt, "%05d-%03d", y, d); if(y < 0) ret = snprintf(str, amt, "%05d-%03d", y, d);
else ret = snprintf(str, amt, extended ? "%04d-%03d" : "%04d%03d", y, d); else ret = snprintf(str, amt, extended ?
"%04d-%03d" : "%04d%03d", y, d);
break; break;
case iso8601_prec_week: case iso8601_prec_week:
iso8601_to_week(&y, &m, &d, &dttz); iso8601_to_week(&y, &m, &d, &dttz);
extended = y < 0 || y > 9999 || details->extended; // ISO year is different /* note: ISO year can differ, so recompute extended flag */
extended = y < 0 || y > 9999 || details->extended;
if(y < 0) snprintf(str, amt, "%05d-W%02d", y, m); if(y < 0) snprintf(str, amt, "%05d-W%02d", y, m);
else snprintf(str, amt, extended ? "%04d-W%02d" : "%04dW%02d", y, m); else snprintf(str, amt, extended ? "%04d-W%02d" : "%04dW%02d", y, m);
return str_orig; return str_orig;
case iso8601_prec_wday: case iso8601_prec_wday:
iso8601_to_week(&y, &m, &d, &dttz); iso8601_to_week(&y, &m, &d, &dttz);
extended = y < 0 || y > 9999 || details->extended; // ISO year is different /* note: ISO year can differ, so recompute extended flag */
extended = y < 0 || y > 9999 || details->extended;
if(y < 0) ret = snprintf(str, amt, "%05d-W%02d-%d", y, m, d); if(y < 0) ret = snprintf(str, amt, "%05d-W%02d-%d", y, m, d);
else ret = snprintf(str, amt, extended ? "%04d-W%02d-%d" : "%04dW%02d%d", y, m, d); else ret = snprintf(str, amt, extended ?
"%04d-W%02d-%d" : "%04dW%02d%d", y, m, d);
break; break;
} }
@ -111,7 +122,8 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date,
break; break;
case iso8601_prec_sec: case iso8601_prec_sec:
ret = snprintf(str, amt, extended ? "T%02d:%02d:%02d" : "T%02d%02d%02d", y, m, d); ret = snprintf(str, amt, extended ?
"T%02d:%02d:%02d" : "T%02d%02d%02d", y, m, d);
break; break;
case iso8601_prec_hourfrac: case iso8601_prec_hourfrac:
@ -121,12 +133,14 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date,
case iso8601_prec_minfrac: case iso8601_prec_minfrac:
frac = m + (d + date->nsec / 1e9) / 60.0; frac = m + (d + date->nsec / 1e9) / 60.0;
ret = snprintf(str, amt, extended ? "T%02d:%#012.9f" : "T%02d%#012.9f", y, frac); ret = snprintf(str, amt, extended ?
"T%02d:%#012.9f" : "T%02d%#012.9f", y, frac);
break; break;
case iso8601_prec_secfrac: case iso8601_prec_secfrac:
frac = d + date->nsec / 1e9; frac = d + date->nsec / 1e9;
ret = snprintf(str, amt, extended ? "T%02d:%02d:%#012.9f" : "T%02d%02d%#012.9f", y, m, frac); ret = snprintf(str, amt, extended ?
"T%02d:%02d:%#012.9f" : "T%02d%02d%#012.9f", y, m, frac);
break; break;
} }
@ -150,8 +164,10 @@ char* iso8601_print(char* str, int amt, const struct iso8601_date* date,
ret -= m * 60; ret -= m * 60;
d = ret; d = ret;
if(d) snprintf(str, amt, extended ? "%02d:%02d:%02d" : "%02d%02d%02d", y, m, d); if(d) snprintf(str, amt, extended ?
else if(m) snprintf(str, amt, extended ? "%02d:%02d" : "%02d%02d", y, m); "%02d:%02d:%02d" : "%02d%02d%02d", y, m, d);
else if(m) snprintf(str, amt, extended ?
"%02d:%02d" : "%02d%02d", y, m);
else snprintf(str, amt, "%02d", y); else snprintf(str, amt, "%02d", y);
} else { } else {
*str++ = 'Z'; *str++ = 'Z';

View File

@ -1,16 +1,17 @@
/* libiso8601/src/libiso8601/400_c_library.c /* libiso8601/src/libiso8601/400_c_library.c
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
// days between 0000-001 and 1970-001 (the unix epoch) /* days between 0000-001 and 1970-001 (the unix epoch) */
#define EPOCH_GDAY (719528) #define EPOCH_GDAY (719528)
void iso8601_now(struct iso8601_date* date, struct iso8601_details* details) void
iso8601_now(struct iso8601_date* date, struct iso8601_details* details)
{ {
static int use_gettimeofday = 0; static int use_gettimeofday = 0;
struct timespec ts; struct timespec ts;
@ -21,7 +22,8 @@ void iso8601_now(struct iso8601_date* date, struct iso8601_details* details)
if(use_gettimeofday || clock_gettime(CLOCK_REALTIME, &ts)) { if(use_gettimeofday || clock_gettime(CLOCK_REALTIME, &ts)) {
use_gettimeofday = 1; use_gettimeofday = 1;
gettimeofday(&tv, 0); gettimeofday(&tv, 0);
ts.tv_sec = tv.tv_sec; if(tv.tv_sec < 0) ts.tv_sec = 0;
else ts.tv_sec = tv.tv_sec;
ts.tv_nsec = tv.tv_usec * 1000L; ts.tv_nsec = tv.tv_usec * 1000L;
} }
@ -44,7 +46,8 @@ void iso8601_now(struct iso8601_date* date, struct iso8601_details* details)
int iso8601_set_sysclock(const struct iso8601_date* date) int
iso8601_set_sysclock(const struct iso8601_date* date)
{ {
static int use_settimeofday = 0; static int use_settimeofday = 0;
struct timeval tv; struct timeval tv;
@ -71,11 +74,16 @@ int iso8601_set_sysclock(const struct iso8601_date* date)
void iso8601_from_ts(struct iso8601_date* date, const struct timespec* ts) void
iso8601_from_ts(struct iso8601_date* date, const struct timespec* ts)
{ {
ldiv_t qr; ldiv_t qr;
qr = ldiv(ts->tv_sec, 86400); qr = ldiv(ts->tv_sec, 86400);
if(ts->tv_sec < 0) {
--qr.quot;
qr.rem += 86400;
}
date->day = EPOCH_GDAY + qr.quot; date->day = EPOCH_GDAY + qr.quot;
date->sec = qr.rem; date->sec = qr.rem;
date->nsec = ts->tv_nsec; date->nsec = ts->tv_nsec;
@ -83,7 +91,8 @@ void iso8601_from_ts(struct iso8601_date* date, const struct timespec* ts)
void iso8601_to_ts(struct timespec* ts, const struct iso8601_date* date) void
iso8601_to_ts(struct timespec* ts, const struct iso8601_date* date)
{ {
ts->tv_sec = 86400L * (date->day - EPOCH_GDAY) + date->sec; ts->tv_sec = 86400L * (date->day - EPOCH_GDAY) + date->sec;
ts->tv_nsec = date->nsec; ts->tv_nsec = date->nsec;
@ -91,11 +100,16 @@ void iso8601_to_ts(struct timespec* ts, const struct iso8601_date* date)
void iso8601_from_tv(struct iso8601_date* date, const struct timeval* tv) void
iso8601_from_tv(struct iso8601_date* date, const struct timeval* tv)
{ {
ldiv_t qr; ldiv_t qr;
qr = ldiv(tv->tv_sec, 86400); qr = ldiv(tv->tv_sec, 86400);
if(tv->tv_sec < 0) {
--qr.quot;
qr.rem += 86400;
}
date->day = EPOCH_GDAY + qr.quot; date->day = EPOCH_GDAY + qr.quot;
date->sec = qr.rem; date->sec = qr.rem;
date->nsec = tv->tv_usec * 1000; date->nsec = tv->tv_usec * 1000;
@ -103,7 +117,8 @@ void iso8601_from_tv(struct iso8601_date* date, const struct timeval* tv)
void iso8601_to_tv(struct timeval* tv, const struct iso8601_date* date) void
iso8601_to_tv(struct timeval* tv, const struct iso8601_date* date)
{ {
tv->tv_sec = 86400L * (date->day - EPOCH_GDAY) + date->sec; tv->tv_sec = 86400L * (date->day - EPOCH_GDAY) + date->sec;
tv->tv_usec = date->nsec / 1000; tv->tv_usec = date->nsec / 1000;
@ -111,11 +126,16 @@ void iso8601_to_tv(struct timeval* tv, const struct iso8601_date* date)
void iso8601_from_time_t(struct iso8601_date* date, const time_t* t) void
iso8601_from_time_t(struct iso8601_date* date, const time_t* t)
{ {
ldiv_t qr; ldiv_t qr;
qr = ldiv(*t, 86400); qr = ldiv(*t, 86400);
if(*t < 0) {
--qr.quot;
qr.rem += 86400;
}
date->day = EPOCH_GDAY + qr.quot; date->day = EPOCH_GDAY + qr.quot;
date->sec = qr.rem; date->sec = qr.rem;
date->nsec = 0; date->nsec = 0;
@ -123,7 +143,8 @@ void iso8601_from_time_t(struct iso8601_date* date, const time_t* t)
void iso8601_to_time_t(time_t* t, const struct iso8601_date* date) void
iso8601_to_time_t(time_t* t, const struct iso8601_date* date)
{ {
*t = 86400L * (date->day - EPOCH_GDAY) + date->sec; *t = 86400L * (date->day - EPOCH_GDAY) + date->sec;
} }

View File

@ -1,7 +1,7 @@
/* libiso8601/src/libiso8601/400_c_library.h /* libiso8601/src/libiso8601/400_c_library.h
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
@ -9,7 +9,8 @@
/*! \defgroup c_library C library integration. /*! \defgroup c_library C library integration.
These functions enable integration with the C library (system call wrappers and conversion). These functions enable integration with the C library (system call wrappers and
conversion).
*/ */
/*!@{*/ /*!@{*/
@ -18,11 +19,11 @@ These functions enable integration with the C library (system call wrappers and
/*! \brief Retrieve the current time. /*! \brief Retrieve the current time.
\param[out] date Current date/time (may be 0), in UTC. \param[out] date Current date/time (may be 0), in UTC. May be 0.
\param[out] details Details (may be 0), including timezone. \param[out] details Details (may be 0), including timezone. May be 0.
Retrieves the current time from the system clock, storing it into \a date and \a details (both Retrieves the current time from the system clock, storing it into \a date and
parameters optional). \a details (both parameters optional).
*/ */
void iso8601_now(struct iso8601_date* date, struct iso8601_details* details); void iso8601_now(struct iso8601_date* date, struct iso8601_details* details);
@ -35,32 +36,65 @@ void iso8601_now(struct iso8601_date* date, struct iso8601_details* details);
\retval 0 on success. \retval 0 on success.
\retval -1 on error (and see \a errno). \retval -1 on error (and see \a errno).
Attempts to set the system clock using \c clock_settime(), falling back to \c settimeofday(). The Attempts to set the system clock using \c clock_settime(), falling back to \c
user will need the \c CAP_SYS_TIME capability to set the clock, otherwise \a errno will be set to settimeofday(). The user will need the \c CAP_SYS_TIME capability to set the
\c EPERM. clock, otherwise \a errno will be set to \c EPERM.
*/ */
int iso8601_set_sysclock(const struct iso8601_date* date); int iso8601_set_sysclock(const struct iso8601_date* date)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
/*! \brief Convert from a struct timespec. */ /*! \brief Convert from a struct timespec. */
void iso8601_from_ts(struct iso8601_date* date, const struct timespec* ts); void iso8601_from_ts(struct iso8601_date* date, const struct timespec* ts)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
/*! \brief Convert to a struct timespec. */ /*! \brief Convert to a struct timespec. */
void iso8601_to_ts(struct timespec* ts, const struct iso8601_date* date); void iso8601_to_ts(struct timespec* ts, const struct iso8601_date* date)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
/*! \brief Convert from a struct timeval. */ /*! \brief Convert from a struct timeval. */
void iso8601_from_tv(struct iso8601_date* date, const struct timeval* tv); void iso8601_from_tv(struct iso8601_date* date, const struct timeval* tv)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
/*! \brief Convert to a struct timeval. */ /*! \brief Convert to a struct timeval. */
void iso8601_to_tv(struct timeval* tv, const struct iso8601_date* date); void iso8601_to_tv(struct timeval* tv, const struct iso8601_date* date)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
/*! \brief Convert from a time_t. */ /*! \brief Convert from a time_t. */
void iso8601_from_time_t(struct iso8601_date* date, const time_t* t); void iso8601_from_time_t(struct iso8601_date* date, const time_t* t)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
/*! \brief Convert to a time_t. */ /*! \brief Convert to a time_t. */
void iso8601_to_time_t(time_t* t, const struct iso8601_date* date); void iso8601_to_time_t(time_t* t, const struct iso8601_date* date)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
/*!@}*/ /*!@}*/
/* 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:syntax=ch.doxygen
*/ */

View File

@ -1,7 +1,7 @@
/* libiso8601/src/libiso8601/400_calc.h /* libiso8601/src/libiso8601/400_calc.h
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
@ -9,8 +9,8 @@
/*! \defgroup calc Conversion and calculation routines. /*! \defgroup calc Conversion and calculation routines.
This set of functions is useful for converting dates and times into formats understood by humans, This set of functions is useful for converting dates and times into formats
and vice versa. understood by humans, and vice versa.
*/ */
/*!@{*/ /*!@{*/
@ -38,7 +38,12 @@ int iso8601_isleap(int year);
\param date Date to convert. \param date Date to convert.
*/ */
void iso8601_to_cal(int* year, int* month, int* day, const struct iso8601_date* date); void iso8601_to_cal(int* year, int* month, int* day,
const struct iso8601_date* date)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
@ -51,11 +56,18 @@ void iso8601_to_cal(int* year, int* month, int* day, const struct iso8601_date*
\retval 0 on success. \retval 0 on success.
\retval -1 on error (and see \a errno). \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 Converts the date specified in \a year, \a month and \a day into \a date.
or \a nsec time members of \a date.
\note Does not touch the \a sec or \a nsec time members of \a date. This means
they will be unchanged after a call to this function. If this will lead to
unexpected results, initialise the structure to 0 first.
*/ */
int iso8601_from_cal(struct iso8601_date* date, int year, int month, int day); int iso8601_from_cal(struct iso8601_date* date, int year, int month, int day)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
@ -66,7 +78,11 @@ int iso8601_from_cal(struct iso8601_date* date, int year, int month, int day);
\param date Date to convert. \param date Date to convert.
*/ */
void iso8601_to_ord(int* year, int* oday, const struct iso8601_date* date); void iso8601_to_ord(int* year, int* oday, const struct iso8601_date* date)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
@ -78,11 +94,18 @@ void iso8601_to_ord(int* year, int* oday, const struct iso8601_date* date);
\retval 0 on success. \retval 0 on success.
\retval -1 on error (and see \a errno). \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 Converts the date specified into \a year and \a oday into \a date.
\a nsec time members of \a date.
\note Does not touch the \a sec or \a nsec time members of \a date. This means
they will be unchanged after a call to this functoin. If this will lead to
unexpected results, initialise the structure to 0 first.
*/ */
int iso8601_from_ord(struct iso8601_date* date, int year, int oday); int iso8601_from_ord(struct iso8601_date* date, int year, int oday)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
@ -94,7 +117,12 @@ int iso8601_from_ord(struct iso8601_date* date, int year, int oday);
\param date Date to convert. \param date Date to convert.
*/ */
void iso8601_to_week(int* year, int* week, int* wday, const struct iso8601_date* date); void iso8601_to_week(int* year, int* week, int* wday,
const struct iso8601_date* date)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
@ -107,8 +135,18 @@ void iso8601_to_week(int* year, int* week, int* wday, const struct iso8601_date*
\retval 0 on success. \retval 0 on success.
\retval -1 on error (and see \a errno). \retval -1 on error (and see \a errno).
Converts the date specified into \a year, \a week and \a wday into \a date.
\note Does not touch the \a sec or \a nsec time members of \a date. This means
they will be unchanged after a call to this functoin. If this will lead to
unexpected results, initialise the structure to 0 first.
*/ */
int iso8601_from_week(struct iso8601_date* date, int year, int week, int wday); int iso8601_from_week(struct iso8601_date* date, int year, int week, int wday)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
@ -119,11 +157,16 @@ int iso8601_from_week(struct iso8601_date* date, int year, int week, int wday);
\param[out] sec Output second. \param[out] sec Output second.
\param date Date/time to convert. \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 Converts the time stored in \a date into wall clock format, storing the result
and \a sec. in \a hour, \a min and \a sec.
*/ */
void iso8601_to_clocktime(int* hour, int* min, int* sec, const struct iso8601_date* date); void iso8601_to_clocktime(int* hour, int* min, int* sec,
const struct iso8601_date* date)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
@ -136,16 +179,25 @@ void iso8601_to_clocktime(int* hour, int* min, int* sec, const struct iso8601_da
\retval 0 on success. \retval 0 on success.
\retval -1 on error (and see \a errno). \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 Converts the time as specified by \a hour, \a min and \a sec, storing the
not touch the \a day (date) member of \a date. result in \a date.
\note Does not touch the \a day (date) member of \a date. This means it will be
unchanged after a call to this function. If this will lead to unexpected
results, initialise the structure to 0 first.
*/ */
int iso8601_from_clocktime(struct iso8601_date* date, int hour, int min, int sec); int iso8601_from_clocktime(struct iso8601_date* date, int hour, int min,
int sec)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
/*!@}*/ /*!@}*/
/* 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:syntax=ch.doxygen
*/ */

View File

@ -1,7 +1,7 @@
/* libiso8601/src/libiso8601/400_leap.h /* libiso8601/src/libiso8601/400_leap.h
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
@ -9,20 +9,23 @@
/*! \defgroup leap Leap second support. /*! \defgroup leap Leap second support.
A set of functions for explicitly dealing with leap seconds. All library functions are implicitly A set of functions for explicitly dealing with leap seconds. All library
leap second aware, but there are occasions when leap seconds must be dealt with explicitly. These functions are implicitly leap second aware, but there are occasions when leap
functions permit this. seconds must be dealt with explicitly. These functions permit this.
Internally, leap seconds are represented as a table of day numbers; each day number present in the Internally, leap seconds are represented as a table of day numbers; each day
table means that the corresponding day has 86401 seconds (a leap second). number present in the table means that the corresponding day has 86401 seconds
(a leap second).
\note The library does not (yet) have support for negative leap seconds. This support will be added \note The library does not (yet) have support for negative leap seconds. This
should a day with a negative leap second ever come. This will need to addressed in the API as support will be added should a day with a negative leap second ever come.
the current API does not support loading a table of negative leap seconds. This will need to addressed in the API as the current API does not support
loading a table of negative leap seconds.
It is possible to create a disk file containing an updated table and to load that file using It is possible to create a disk file containing an updated table and to load
\ref iso8601_leap_table_load (or to explicitly use an existing in-memory table with that file using \ref iso8601_leap_table_load (or to explicitly use an existing
\ref iso8601_leap_table_set). The format of the on-disk file is: in-memory table with \ref iso8601_leap_table_set). The format of the on-disk
file is:
<pre># integers are stored big-endian <pre># integers are stored big-endian
[8*char] signature, "/O9PdPZI" [8*char] signature, "/O9PdPZI"
@ -43,14 +46,19 @@ It is possible to create a disk file containing an updated table and to load tha
\retval 86400 day with no leap second. \retval 86400 day with no leap second.
\retval 86401 day with one leap second. \retval 86401 day with one leap second.
Returns the duration of a day \a date, in seconds. This function takes leap seconds into account and Returns the duration of a day \a date, in seconds. This function takes leap
may be used to determine if a day contains a leap second or not. seconds into account and may be used to determine if a day contains a leap
second or not.
\note There have not yet been any days requiring a negative leap second, so at present 86399 will \note There have not yet been any days requiring a negative leap second, so at
never be returned. present 86399 will never be returned.
*/ */
int iso8601_seconds_leap(const struct iso8601_date* date); int iso8601_seconds_leap(const struct iso8601_date* date)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
@ -60,13 +68,19 @@ int iso8601_seconds_leap(const struct iso8601_date* date);
\param end The end date. \param end The end date.
\returns Number of leap seconds elapsed. \returns Number of leap seconds elapsed.
Computes the number of leap seconds that have elapsed between two days. Note that this is the sum of Computes the number of leap seconds that have elapsed between two days. Note
such leap seconds, so it will be 0 if (for example) there is one positive leap second and one that this is the sum of such leap seconds, so it will be 0 if (for example)
negative leap second. The ordering of the dates is important; if \a start is after \a end, then the there is one positive leap second and one negative leap second. The ordering of
value returned will be negative (for positive leap seconds). the dates is important; if \a start is after \a end, then the value returned
will be negative (for positive leap seconds).
*/ */
int iso8601_leap_elapsed(const struct iso8601_date* start, const struct iso8601_date* end); int iso8601_leap_elapsed(const struct iso8601_date* start,
const struct iso8601_date* end)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
@ -75,33 +89,42 @@ int iso8601_leap_elapsed(const struct iso8601_date* start, const struct iso8601_
\param new_table Array of day numbers on which leap seconds occur. \param new_table Array of day numbers on which leap seconds occur.
\param new_size Number of entries in array. \param new_size Number of entries in array.
This function can be used to update the table of leap seconds at runtime. The \a new_table argument This function can be used to update the table of leap seconds at runtime. The
points to an array of integers, each entry being the day number containing a leap second. The array \a new_table argument points to an array of integers, each entry being the day
must be sorted so that lower day numbers appear towards the start of the array. \a new_size gives number containing a leap second. The array must be sorted so that lower day
the number of entries in the array. \a new_table must persist in memory as long as library functions numbers appear towards the start of the array. \a new_size gives the number of
are in use. entries in the array. \a new_table must persist in memory as long as library
functions are in use.
\warning If negative leap seconds are ever used, this function will not support them. There may need \warning If negative leap seconds are ever used, this function will not support
to be an ABI change in future to solve this problem. them. There may need to be an ABI change in future to solve this problem.
*/ */
void iso8601_leap_table_set(int* new_table, int new_size) __attribute__((nonnull)); void iso8601_leap_table_set(int* new_table, int new_size)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
/*! \brief Load new table of leap seconds from disk. /*! \brief Load new table of leap seconds from disk.
\param fname Filename. \param fname Filename. May be 0 for system default.
\retval 0 on success. \retval 0 on success.
\retval -1 on error (and see \a errno). \retval -1 on error (and see \a errno).
This function attempts to load a new table of leap seconds from disk, using the filename \a fname. This function attempts to load a new table of leap seconds from disk, using the
If the table is loaded successfully, it will be set with \ref iso8601_leap_table_set(). On any filename \a fname. If \a fname is not specified, the system default (set at
error, -1 will be returned, and \a errno will be set appropriately. If \a errno is \c EINVAL, then compile time) will be used.
the file does not contain a valid leap second table.
If the table is loaded successfully, it will be set with \ref
iso8601_leap_table_set(). On any error, -1 will be returned, and \a errno will
be set appropriately. If \a errno is \c EINVAL, then the file does not contain
a valid leap second table.
*/ */
int iso8601_leap_table_load(const char* fname) __attribute__((nonnull)); int iso8601_leap_table_load(const char* fname);

View File

@ -1,13 +1,14 @@
/* libiso8601/src/libiso8601/400_manip.c /* libiso8601/src/libiso8601/400_manip.c
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
int iso8601_lt(const struct iso8601_date* d1, const struct iso8601_date* d2) int
iso8601_lt(const struct iso8601_date* d1, const struct iso8601_date* d2)
{ {
if(d1->day < d2->day) return 1; if(d1->day < d2->day) return 1;
if(d1->day > d2->day) return 0; if(d1->day > d2->day) return 0;
@ -19,7 +20,8 @@ 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_lte(const struct iso8601_date* d1, const struct iso8601_date* d2)
{ {
if(d1->day < d2->day) return 1; if(d1->day < d2->day) return 1;
if(d1->day > d2->day) return 0; if(d1->day > d2->day) return 0;
@ -31,19 +33,37 @@ 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) int
iso8601_eq(const struct iso8601_date* d1, const struct iso8601_date* d2)
{ {
return (d1->day == d2->day) && (d1->sec == d2->sec) && (d1->nsec == d2->nsec); return (d1->day == d2->day) && (d1->sec == d2->sec)
&& (d1->nsec == d2->nsec);
} }
void iso8601_add_elapsed(struct iso8601_date* date, const struct iso8601_elapsed* per) int
iso8601_cmp(const struct iso8601_date* d1, const struct iso8601_date* d2)
{
if(d1->day < d2->day) return -1;
if(d1->day > d2->day) return 1;
if(d1->sec < d2->sec) return -1;
if(d1->sec > d2->sec) return 1;
if(d1->nsec < d2->nsec) return -1;
if(d1->nsec > d2->nsec) return 1;
return 0;
}
void
iso8601_add_elapsed(struct iso8601_date* date,
const struct iso8601_elapsed* per)
{ {
div_t qr; div_t qr;
int leapcorrect; int leapcorrect;
/* work out number to advance `day' by */ /* work out number to advance day by */
qr = div(per->sec, 86400); qr = div(per->sec, 86400);
leapcorrect = _leap_elapsed_day(date->day, date->day + qr.quot); leapcorrect = _leap_elapsed_day(date->day, date->day + qr.quot);
date->day += qr.quot; date->day += qr.quot;
@ -68,12 +88,14 @@ void iso8601_add_elapsed(struct iso8601_date* date, const struct iso8601_elapsed
void iso8601_subtract_elapsed(struct iso8601_date* date, const struct iso8601_elapsed* per) void
iso8601_subtract_elapsed(struct iso8601_date* date,
const struct iso8601_elapsed* per)
{ {
div_t qr; div_t qr;
int leapcorrect; int leapcorrect;
/* work out number to advance `day' by */ /* work out number to advance day by */
qr = div(per->sec, 86400); qr = div(per->sec, 86400);
leapcorrect = _leap_elapsed_day(date->day - qr.quot, date->day); leapcorrect = _leap_elapsed_day(date->day - qr.quot, date->day);
date->day -= qr.quot; date->day -= qr.quot;
@ -98,7 +120,9 @@ void iso8601_subtract_elapsed(struct iso8601_date* date, const struct iso8601_el
void iso8601_add_multiple(struct iso8601_date* date, const struct iso8601_elapsed* per, int n) void
iso8601_add_multiple(struct iso8601_date* date,
const struct iso8601_elapsed* per, int n)
{ {
long long nsec; long long nsec;
lldiv_t qr; lldiv_t qr;
@ -115,7 +139,8 @@ void iso8601_add_multiple(struct iso8601_date* date, const struct iso8601_elapse
void iso8601_difference(const struct iso8601_date* d1, const struct iso8601_date* d2, void
iso8601_difference(const struct iso8601_date* d1, const struct iso8601_date* d2,
struct iso8601_elapsed* per, int* sign) struct iso8601_elapsed* per, int* sign)
{ {
const struct iso8601_date* e1, * e2; const struct iso8601_date* e1, * e2;
@ -147,6 +172,32 @@ void iso8601_difference(const struct iso8601_date* d1, const struct iso8601_date
int
iso8601_elapsed_div(const struct iso8601_elapsed* num,
const struct iso8601_elapsed* denom, struct iso8601_elapsed* remain)
{
unsigned long long pnum, pdenom;
lldiv_t val, v2;
pnum = num->sec;
pnum *= BILLION;
pnum += num->nsec;
pdenom = denom->sec;
pdenom *= BILLION;
pdenom += denom->nsec;
val = lldiv(pnum, pdenom);
if(remain) {
v2 = lldiv(val.rem, BILLION);
remain->sec = v2.quot;
remain->nsec = v2.rem;
}
return val.quot;
}
/* 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

View File

@ -1,7 +1,7 @@
/* libiso8601/src/libiso8601/400_manip.h /* libiso8601/src/libiso8601/400_manip.h
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
@ -9,8 +9,8 @@
/*! \defgroup manip Manipulation routines. /*! \defgroup manip Manipulation routines.
This set of functions is useful for performing arithmetic etc. on dates. It uses This set of functions is useful for performing arithmetic etc. on dates. It
struct iso8601_elapsed to represent the magnitude of time differences. uses struct \ref iso8601_elapsed to represent the magnitude of time differences.
*/ */
/*!@{*/ /*!@{*/
@ -25,7 +25,11 @@ struct iso8601_elapsed to represent the magnitude of time differences.
\retval 0 otherwise \retval 0 otherwise
*/ */
int iso8601_lt(const struct iso8601_date* d1, const struct iso8601_date* d2); int iso8601_lt(const struct iso8601_date* d1, const struct iso8601_date* d2)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
@ -37,7 +41,11 @@ int iso8601_lt(const struct iso8601_date* d1, const struct iso8601_date* d2);
\retval 0 otherwise \retval 0 otherwise
*/ */
int iso8601_lte(const struct iso8601_date* d1, const struct iso8601_date* d2); int iso8601_lte(const struct iso8601_date* d1, const struct iso8601_date* d2)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
@ -49,7 +57,28 @@ int iso8601_lte(const struct iso8601_date* d1, const struct iso8601_date* d2);
\retval 0 otherwise \retval 0 otherwise
*/ */
int iso8601_eq(const struct iso8601_date* d1, const struct iso8601_date* d2); int iso8601_eq(const struct iso8601_date* d1, const struct iso8601_date* d2)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
/*! \brief Comparison (for qsort et al.).
\param d1 First date to compare.
\param d2 Second date to compare.
\retval -1 if \a d1 &lt; \a d2
\retval 0 if \a d1 == \a d2
\retval 1 if \a d1 &gt; \a d2
*/
int iso8601_cmp(const struct iso8601_date* d1, const struct iso8601_date* d2)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
@ -59,7 +88,12 @@ int iso8601_eq(const struct iso8601_date* d1, const struct iso8601_date* d2);
\param per Period to advance date/time by. \param per Period to advance date/time by.
*/ */
void iso8601_add_elapsed(struct iso8601_date* date, const struct iso8601_elapsed* per); void iso8601_add_elapsed(struct iso8601_date* date,
const struct iso8601_elapsed* per)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
@ -69,7 +103,12 @@ void iso8601_add_elapsed(struct iso8601_date* date, const struct iso8601_elapsed
\param per Period to regress date/time by. \param per Period to regress date/time by.
*/ */
void iso8601_subtract_elapsed(struct iso8601_date* date, const struct iso8601_elapsed* per); void iso8601_subtract_elapsed(struct iso8601_date* date,
const struct iso8601_elapsed* per)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
@ -79,11 +118,17 @@ void iso8601_subtract_elapsed(struct iso8601_date* date, const struct iso8601_el
\param per Period to advance date/time by. \param per Period to advance date/time by.
\param n Multiple of \a per. \param n Multiple of \a per.
Adds \a n multiples of \a per to \a date. \a n may be 0 or negative. The result is stored in Adds \a n multiples of \a per to \a date. \a n may be 0 or negative. The result
\a date. This is an efficient implementation which avoids loops, but it does use 64-bit arithmetic. is stored in \a date. This is an efficient implementation which avoids loops,
but it does use 64-bit arithmetic.
*/ */
void iso8601_add_multiple(struct iso8601_date* date, const struct iso8601_elapsed* per, int n); void iso8601_add_multiple(struct iso8601_date* date,
const struct iso8601_elapsed* per, int n)
#ifndef DOXYGEN
__attribute__((nonnull))
#endif
;
@ -94,13 +139,39 @@ void iso8601_add_multiple(struct iso8601_date* date, const struct iso8601_elapse
\param[out] per Magnitude of period elapsed between two dates. Pointer may be 0. \param[out] per Magnitude of period elapsed between two dates. Pointer may be 0.
\param[out] sign Set to sign of difference (-1 or +1). Pointer may be 0. \param[out] sign Set to sign of difference (-1 or +1). Pointer may be 0.
This function will perform the calculation <code>|d1 - d2|</code>, storing the result in \a per (if This function will perform the calculation <code>|d1 - d2|</code>, storing the
it is not a null pointer). The sign of the result is stored in \a sign (if it is not a null result in \a per (if it is not a null pointer). The sign of the result is
pointer), i.e. -1 if \a d2 &gt; \a d1 or +1 if \a d2 &lt;= \a d1. stored in \a sign (if it is not a null pointer), i.e. -1 if \a d2 &gt; \a d1 or
+1 if \a d2 &lt;= \a d1.
*/ */
void iso8601_difference(const struct iso8601_date* d1, const struct iso8601_date* d2, void iso8601_difference(const struct iso8601_date* d1,
struct iso8601_elapsed* per, int* sign); const struct iso8601_date* d2, struct iso8601_elapsed* per, int* sign)
#ifndef DOXYGEN
__attribute__((nonnull(1,2)))
#endif
;
/*! \brief Divide one period by another.
\param num Numerator.
\param denom Denominator (divisor).
\param[out] remain Remainder. May be 0.
\returns Number of times \a denom divides into \a num.
This function computes the number of times that \a denom can be divided into \a
num, returning that number. If desired, the remaining period which could not be
divided can be written into \a remain. Uses 64-bit arithmetic internally.
*/
int iso8601_elapsed_div(const struct iso8601_elapsed* num,
const struct iso8601_elapsed* denom, struct iso8601_elapsed* remain)
#ifndef DOXYGEN
__attribute__((nonnull(1,2)));
#endif
;

View File

@ -1,10 +1,14 @@
/* libiso8601/src/libiso8601/999_BottomHeader.h /* libiso8601/src/libiso8601/999_BottomHeader.h
* *
* (c)2006, Laurence Withers, <l@lwithers.me.uk>. * (c)2006-2010, Laurence Withers, <l@lwithers.me.uk>.
* Released under the GNU GPLv2. See file COPYING or * Released under the GNU GPLv3. See file COPYING or
* http://www.gnu.org/copyleft/gpl.html for details. * http://www.gnu.org/copyleft/gpl.html for details.
*/ */
#ifdef __cplusplus
}
#endif
#endif #endif
/* options for text editors /* options for text editors

View File

@ -7,6 +7,7 @@ build_dir_tree "${INCLUDEDIR}" || return 1
# install library # install library
echo "Installing libraries into '${LIBDIR}'" echo "Installing libraries into '${LIBDIR}'"
source src/libiso8601/soversion
install_file ${libiso8601} ${LIBDIR} 0755 || return 1 install_file ${libiso8601} ${LIBDIR} 0755 || return 1
BASE="${libiso8601_BASE}.so" BASE="${libiso8601_BASE}.so"
MAJOR="${BASE}.${SOMAJOR}" MAJOR="${BASE}.${SOMAJOR}"
@ -33,5 +34,4 @@ do_cmd_redir "${CONFFILE}" sed \
do_cmd chmod 0755 "${CONFFILE}" do_cmd chmod 0755 "${CONFFILE}"
print_success "Done" print_success "Done"
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: syntax=sh:expandtab:ts=4:sw=4 # vim: syntax=sh:expandtab:ts=4:sw=4

View File

@ -14,7 +14,9 @@ then
libiso8601="obj/${libiso8601_BASE}.so.${SOMAJOR}.${SOMICRO}" libiso8601="obj/${libiso8601_BASE}.so.${SOMAJOR}.${SOMICRO}"
libiso8601_DEP_CFLAGS="" libiso8601_DEP_CFLAGS=""
libiso8601_DEP_LIBS="-lrt" libiso8601_DEP_LIBS="-lrt"
SO_EXTRA="-std=gnu99 -D_GNU_SOURCE ${libiso8601_DEP_CFLAGS} ${libiso8601_DEP_LIBS} -lc" SO_EXTRA="${libiso8601_DEP_CFLAGS} ${libiso8601_DEP_LIBS} -lc \
-D_GNU_SOURCE -std=gnu99 \
-DDEFAULT_LEAP_TABLE=\"${DEFAULT_LEAP_TABLE}\""
echo "Building library ${libiso8601}..." echo "Building library ${libiso8601}..."
@ -52,5 +54,4 @@ then
libiso8601_HEADER=${HDR} libiso8601_HEADER=${HDR}
fi fi
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: syntax=sh:expandtab:ts=4:sw=4 # vim: syntax=sh:expandtab:ts=4:sw=4

View File

@ -17,5 +17,4 @@ then
libiso8601_MONOLITHIC=1 libiso8601_MONOLITHIC=1
MONOLITHIC_DOC="${MONOLITHIC_DOC} ${HDR}" MONOLITHIC_DOC="${MONOLITHIC_DOC} ${HDR}"
fi fi
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: syntax=sh:expandtab:ts=4:sw=4 # vim: syntax=sh:expandtab:ts=4:sw=4

View File

@ -95,4 +95,3 @@ true
# vim: syntax=sh:expandtab:ts=4:sw=4 # vim: syntax=sh:expandtab:ts=4:sw=4
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;

View File

@ -1,8 +1,8 @@
# libiso8601/src/libiso8601/soversion # libiso8601/src/libiso8601/soversion
# #
# (c)2007, Laurence Withers, <l@lwithers.me.uk>. # Copyright: ©20072011, Güralp Systems Ltd.
# Released under the GNU GPLv3. See file COPYING or # Author: Laurence Withers <lwithers@guralp.com>
# http://www.gnu.org/copyleft/gpl.html for details. # License: GPLv3
# #
@ -12,4 +12,4 @@
SOMAJOR=1 SOMAJOR=1
# SOMICRO is bumped every time there is a binary-compatible release. # SOMICRO is bumped every time there is a binary-compatible release.
SOMICRO=3 SOMICRO=10

View File

@ -8,7 +8,8 @@ build_target libiso8601
if [ -z ${setisodate_BUILT} ] if [ -z ${setisodate_BUILT} ]
then then
setisodate="obj/setisodate" setisodate="obj/setisodate"
EXTRAS="${libiso8601} ${libiso8601_DEP_CFLAGS} ${libiso8601_DEP_LIBS}" EXTRAS="-std=gnu99 -D_GNU_SOURCE -DAPP_NAME=\"setisodate\" \
${libiso8601} ${libiso8601_DEP_CFLAGS} ${libiso8601_DEP_LIBS}"
echo "Building application ${setisodate}..." echo "Building application ${setisodate}..."
@ -39,5 +40,4 @@ then
fi fi
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: syntax=sh:expandtab:ts=4:sw=4 # vim: syntax=sh:expandtab:ts=4:sw=4

View File

@ -8,5 +8,4 @@ echo "Installing binaries into '${SBINDIR}'"
install_file "${setisodate}" "${SBINDIR}" 0755 || return 1 install_file "${setisodate}" "${SBINDIR}" 0755 || return 1
print_success "Done" print_success "Done"
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: syntax=sh:expandtab:ts=4:sw=4 # vim: syntax=sh:expandtab:ts=4:sw=4

View File

@ -14,5 +14,4 @@ then
MONOLITHIC_DOC="${MONOLITHIC_DOC} ${SRC}" MONOLITHIC_DOC="${MONOLITHIC_DOC} ${SRC}"
fi fi
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: syntax=sh:expandtab:ts=4:sw=4 # vim: syntax=sh:expandtab:ts=4:sw=4

View File

@ -1,3 +1 @@
source src/tests/build.tests source src/tests/build.tests
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: syntax=sh:expandtab:ts=4:sw=4

View File

@ -7,14 +7,14 @@ build_target libiso8601 || return 1
if [ -z ${tests_BUILT} ] if [ -z ${tests_BUILT} ]
then then
LIBS="${libiso8601} ${libiso8601_DEP_CFLAGS} ${libiso8601_DEP_LIBS} " LIBS="${libiso8601} ${libiso8601_DEP_CFLAGS} ${libiso8601_DEP_LIBS} "
EXTRAS="-D_GNU_SOURCE" EXTRAS="-lm"
echo "Building test programs..." echo "Building test programs..."
do_cmd mkdir -p obj/tests || return 1 do_cmd mkdir -p obj/tests || return 1
for SRC in src/tests/*.c for SRC in src/tests/*.c
do do
TEST="obj/tests/$(basename ${SRC} | sed -e 's,.c$,,')" TEST="obj/tests/$(basename "${SRC}" ".c")"
MODIFIED=0 MODIFIED=0
for file in ${LIBS} ${SRC} src/tests/build.tests for file in ${LIBS} ${SRC} src/tests/build.tests
do do
@ -25,14 +25,9 @@ then
fi fi
done done
case "${TEST}" in
obj/tests/manip) TEST_EXTRAS="-lm" ;;
*) TEST_EXTRAS="" ;;
esac
if [ ${MODIFIED} -ne 0 ] if [ ${MODIFIED} -ne 0 ]
then then
do_cmd ${CC} -Iobj ${CFLAGS} -o ${TEST} ${SRC} ${LIBS} ${EXTRAS} ${TEST_EXTRAS} || return 1 do_cmd ${CC} -Iobj ${CFLAGS} -o ${TEST} ${SRC} ${LIBS} ${EXTRAS} || return 1
print_success "Built ${TEST}" print_success "Built ${TEST}"
else else
print_success "${TEST} is up to date" print_success "${TEST} is up to date"
@ -44,5 +39,4 @@ then
tests_BUILT=1 tests_BUILT=1
fi fi
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: syntax=sh:expandtab:ts=4:sw=4 # vim: syntax=sh:expandtab:ts=4:sw=4

View File

@ -1,9 +1,9 @@
/* libiso8601/src/tests/???.c /* libiso8601/src/tests/xxx.c
* *
* (c)2007, Laurence Withers, <l@lwithers.me.uk>. * Copyright: ©20072011, Güralp Systems Ltd.
* Released under the GNU GPLv3. See file COPYING or * Author: Laurence Withers <lwithers@guralp.com>
* http://www.gnu.org/copyleft/gpl.html for details. * License: GPLv3
*/ */
#include "iso8601.h" #include "iso8601.h"
@ -12,7 +12,8 @@
int main(int argc, char* argv[]) int
main(int argc, char* argv[])
{ {
int ret = 0; int ret = 0;
@ -30,7 +31,8 @@ int main(int argc, char* argv[])
return ret; return ret;
} }
/* options for text editors /* options for text editors
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
vim: expandtab:ts=4:sw=4 vim: expandtab:ts=4:sw=4
*/ */

View File

@ -1,8 +1,8 @@
# libiso8601/version # libiso8601/version
# #
# (c)2007, Laurence Withers, <l@lwithers.me.uk>. # Copyright: ©20072011, Güralp Systems Ltd.
# Released under the GNU GPLv3. See file COPYING or # Author: Laurence Withers <lwithers@guralp.com>
# http://www.gnu.org/copyleft/gpl.html for details. # License: GPLv3
# #
@ -11,7 +11,6 @@
# expected to be in 'major.minor.micro' format. # expected to be in 'major.minor.micro' format.
VERMAJOR=0 VERMAJOR=0
VERMINOR=3 VERMINOR=3
VERMICRO=5 VERMICRO=15
# kate: replace-trailing-space-save true; space-indent true; tab-width 4;
# vim: expandtab:ts=4:sw=4:syntax=sh # vim: expandtab:ts=4:sw=4:syntax=sh