Skip to content

Latest commit

 

History

History
714 lines (463 loc) · 22.9 KB

API.pod

File metadata and controls

714 lines (463 loc) · 22.9 KB

NAME

dt - Lightweight C library for date arithmetic and date conversion using the proleptic Gregorian calendar

FEATURES

  • Portable, C89

  • No sytem calls

  • No broken-down date structures

  • Fast arithmetic and compact representation of dates

  • Follows the ISO 8601 conventions

  • Conversion between all ISO 8601 date representations

  • Good test coverage

INTRODUCTION

Dates values dt_t are represented as an integer denoting the number of days since the zero epoch, December 31 of the year zero in the proleptic Gregorian calendar. The supported date range is from -5879610-06-22 (INT32_MIN) to +5879611-07-11 (INT32_MAX).

Functions provided by this library doesn't guard against integer overflows, it's the callers responsibility to ensure that dates and date arithmetic is within the supported range.

FUNCTIONS

dt_from_cjdn

dt_t dt_from_cjdn(int cjdn);

Returns a date corresponding to the given chronological Julian day number cjdn.

dt_from_rdn

dt_t dt_from_rdn(int rdn);

Returns a date corresponding to the given Rata Die number rdn.

dt_from_easter

dt_t dt_from_easter(int year, dt_computus_t computus);

Returns a date corresponding to the Easter Sunday for the given year. The parameter computus specifies the Easter calculation. Returns 0 if the given year is non-positive.

(computus = DT_WESTERN)

Calculation based on the Gregorian calendar.

(computus = DT_ORTHODOX)

Calculation based on the Julian calendar with the Julian date converted to the equivalent Gregorian date.

Example:

/* Easter Sunday */
dt = dt_from_easter(2012, DT_WESTERN);

/* Good Friday, 2 days before Easter */
dt = dt_from_easter(2012, DT_WESTERN) - 2;

/* Pentecost, 49 days after Easter (50th day of Easter) */
dt = dt_from_easter(2012, DT_WESTERN) + 49;

dt_from_struct_tm

dt_t dt_from_struct_tm(const struct tm *tm);

Returns a date corresponding to the given structure tm. Folowing members of the tm structure must be set: tm_year, tm_mon and tm_mday. The members tm_mon and tm_mday may be outside usual range and will be normalized during the conversion.

dt_from_yd

dt_t dt_from_yd(int year, int day);

Returns a date corresponding to the given ordinal date: year and day of the year (1-366). The day may be outside usual range and will be normalized during the conversion.

dt_from_ymd

dt_t dt_from_ymd(int year, int month, int day);

Returns a date corresponding to the given calendar date: year, month of the year (1-12), and day of the month (1-31). The month and day may be outside their usual ranges and will be normalized during the conversion. For example, January 32 converts to February 1.

dt_from_ywd

dt_t dt_from_ywd(int year, int week, int day);

Returns a date corresponding to the given week date: year, week of the year (1-53), and day of the week (1-7). The week and day may be outside their usual ranges and will be normalized during the conversion.

dt_from_yqd

dt_t dt_from_yqd(int year, int quarter, int day);

Returns a date corresponding to the given quarter date: year, quarter of the year (1-4), and day of the quarter (1-92). The quarter and day may be outside their usual ranges and will be normalized during the conversion.

dt_valid_yd

bool dt_valid_yd(int year, int day);

Returns a boolean indicating whether or not the given ordinal date: year and day of the year constitute a valid date.

dt_valid_ymd

bool dt_valid_ymd(int year, int month, int day);

Returns a boolean indicating whether or not the given calendar date: year, month of the year and day of the month constitute a valid date.

dt_valid_yqd

bool dt_valid_yqd(int year, int quarter, int day);

Returns a boolean indicating whether or not the given quarter date: year, quarter of the year and day of the quarter constitute a valid date.

dt_valid_ywd

bool dt_valid_ywd(int year, int week, int day);

Returns a boolean indicating whether or not the given week date: year, week of the year and day of the week constitute a valid date.

dt_to_struct_tm

void dt_to_struct_tm(dt_t dt, struct tm *tm);

Converts the given date dt to a broken down time struct *tm. Following members of the tm structure are set: tm_year, tm_mon, tm_mday, tm_wday and tm_yday.

dt_to_yd

void dt_to_yd(dt_t dt, int *year, int *day);

Converts the given date dt to the corresponding ordinal date: year and day of the year (1-366). The pointer parameters may be NULL for any of the results that are not required.

dt_to_ymd

void dt_to_ymd(dt_t dt, int *year, int *month, int *day);

Converts the given date dt to the corresponding calendar date: year, month of the year (1-12) and day of the month (1-31). The pointer parameters may be NULL for any of the results that are not required.

dt_to_yqd

void dt_to_yqd(dt_t dt, int *year, int *quarter, int *day);

Converts the given date dt to the corresponding quarter date: year, quarter of the year (1-4) and day of the quarter (1-92). The pointer parameters may be NULL for any of the results that are not required.

dt_to_ywd

void dt_to_ywd(dt_t dt, int *year, int *week, int *day);

Converts the given date dt to the corresponding week date: year, week of the year (1-53) and day of the week (1=Monday to 7=Sunday). The pointer parameters may be NULL for any of the results that are not required.

dt_cjdn

int dt_cjdn(dt_t dt);

Returns the chronological Julian day number for the given date dt.

dt_rdn

int dt_rdn(dt_t dt);

Returns the Rata Die number for the given date dt.

dt_year

int dt_year(dt_t dt);

Returns the year for the given date dt.

dt_quarter

int dt_quarter(dt_t dt);

Returns the quarter of the year (1-4) for the given date dt.

dt_month

int dt_month(dt_t dt);

Returns the month of the year (1-12) for the given date dt.

dt_doy

int dt_doy(dt_t dt);

Returns the day of the year (1-366) for the given date dt.

dt_doq

int dt_doq(dt_t dt);

Returns the day of the quarter (1-92) for the given date dt.

dt_dom

int dt_dom(dt_t dt);

Returns the day of the month (1-31) for the given date dt.

dt_dow

int dt_dow(dt_t dt);

Returns the day of the week (1=Monday to 7=Sunday) for the given date dt.

dt_woy

int dt_woy(dt_t dt);

Returns the week of the year (1-53) for the given date dt.

dt_yow

int dt_yow(dt_t dt);

Returns the year of the week for the given date dt.

dt_start_of_year

dt_t dt_start_of_year(dt_t dt, int offset);

Returns a date set to the first day of the year for the given date dt. The parameter offset specifies the number of years before (negative) or after (positive) the given date.

dt_start_of_quarter

dt_t dt_start_of_quarter(dt_t dt, int offset);

Returns a date set to the first day of the quarter for the given date dt. The parameter offset specifies the number of quarters before (negative) or after (positive) the given date.

dt_start_of_month

dt_t dt_start_of_month(dt_t dt, int offset);

Returns a date set to the first day of the month for the given date dt. The parameter offset specifies the number of months before (negative) or after (positive) the given date.

dt_start_of_week

dt_t dt_start_of_week(dt_t dt, dt_dow_t first);

Returns a date set to the first day of the week for the given date dt. The parameter first specifies the first day of the week.

dt_end_of_year

dt_t dt_end_of_year(dt_t dt, int offset);

Returns a date set to the last day of the year for the given date dt. The parameter offset specifies the number of years before (negative) or after (positive) the given date.

dt_end_of_quarter

dt_t dt_end_of_quarter(dt_t dt, int offset);

Returns a date set to the last day of the quarter for the given date dt. The parameter offset specifies the number of quarters before (negative) or after (positive) the given date.

dt_end_of_month

dt_t dt_end_of_month(dt_t dt, int offset);

Returns a date set to the last day of the month for the given date dt. The parameter offset specifies the number of months before (negative) or after (positive) the given date.

dt_end_of_week

dt_t dt_end_of_week(dt_t dt, dt_dow_t first);

Returns a date set to the last day of the week for the given date dt. The parameter first specifies the first day of the week.

dt_nth_dow

dt_t dt_nth_dow(dt_t dt, int nth, dt_dow_t day);

Returns a date set to the nth occurrence of the given day of week for given date dt. The parameter day specifies the day of week.

Example:

/* Birthday of Martin Luther King, Jr., the third Monday in January */
dt = dt_from_ymd(2012, 1, 1);
dt = dt_nth_dow(dt, 3, DT_MONDAY);

/* Memorial Day, the last Monday in May */
dt = dt_from_ymd(2012, 5, 31);
dt = dt_nth_dow(dt, -1, DT_MONDAY);

/* Thanksgiving Day, the fourth Thursday in November */
dt = dt_from_ymd(2012, 11, 1);
dt = dt_nth_dow(dt, 4, DT_THURSDAY);

/* Penultimate Monday in the second quarter */
dt = dt_from_yqd(2012, 2, 91);
dt = dt_nth_dow(dt, -2, DT_MONDAY);

/* 50th Wednesday of the year */
dt = dt_from_ymd(2012, 1, 1);
dt = dt_nth_dow(dt, 50, DT_WEDNESDAY);

dt_next_dow

dt_t dt_next_dow(dt_t dt, dt_dow_t day, bool current);

Returns a date set to the next or current day of week for the given date dt. The parameter day specifies the day of week. The parameter current specifies whether or not the returned date must succeed the given date.

dt_prev_dow

dt_t dt_prev_dow(dt_t dt, dt_dow_t day, bool current);

Returns a date set to the previous or current day of week for the given date dt. The parameter day specifies the day of week. The parameter current specifies whether or not the returned date must precede the given date.

dt_next_weekday

dt_t dt_next_weekday(dt_t dt, bool current);

Returns a date set to the next or current weekday (Monday through Friday) for the given date dt. The parameter current specifies whether or not the returned date must succeed the given date.

dt_prev_weekday

dt_t dt_prev_weekday(dt_t dt, bool current);

Returns a date set to the previous or current weekday (Monday through Friday) for the given date dt. The parameter current specifies whether or not the returned date must precede the given date.

dt_add_years

dt_t dt_add_years(dt_t dt, int years, dt_adjust_t adjust);

Returns a date with the given number of years added. The parameter adjust defines the behaviour when the resulting year has one day less than the year of the given date.

(adjust = DT_EXCESS) If the resulting year has one day less than the year of the given date, then the result is counted forward or backward into the next or previous year by the excessive day. Otherwise, the result has the same day of year as the given date. For example:

2012-366 + 1 year = 2014-001 *
2011-365 + 1 year = 2012-365

(adjust = DT_LIMIT) If the resulting year has one day less than the year of the given date, then the result is the last day of the resulting year. Otherwise, the result has the same day of year as the given date. For example:

2012-366 + 1 year = 2013-365 *
2011-365 + 1 year = 2012-365

(adjust = DT_SNAP) If the given date is the last day of the year or if the resulting year has one day less than the year of the given date, then the result is the last day of the resulting year. Otherwise, the result has the same day of year as the given date. For example:

2012-366 + 1 year = 2013-365 *
2011-365 + 1 year = 2012-366 *

dt_add_quarters

dt_t dt_add_quarters(dt_t dt, int quarters, dt_adjust_t adjust);

Returns a date with the given number of quarters added. The parameter adjust defines the behaviour when the resulting quarter has fewer days than the day of the quarter for the given date.

(adjust = DT_EXCESS) If the resulting quarter has fewer days than the day of quarter for the given date, then the result is counted forward or backward into the next or previous quarter by the number of excessive days. Otherwise, the result has the same day of quarter as the given date. For example:

2011-Q4-92 + 1 quarter = 2012-Q2-01 *
2012-Q2-91 + 1 quarter = 2012-Q3-91

(adjust = DT_LIMIT) If the resulting quarter has fewer days than the day of quarter for the given date, then the result is the last day of the resulting quarter. Otherwise, the result has the same day of quarter as the given date. For example:

2011-Q4-92 + 1 quarter = 2012-Q1-91 *
2012-Q2-91 + 1 quarter = 2012-Q3-91

(adjust = DT_SNAP) If the given date is the last day of the quarter or if the resulting quarter has fewer days than the day of quarter for the given date, then the result is the last day of the resulting quarter. Otherwise, the result has the same day of quarter as the given date. For example:

2011-Q4-92 + 1 quarter = 2012-Q1-91 *
2012-Q2-91 + 1 quarter = 2012-Q3-92 *

dt_add_months

dt_t dt_add_months(dt_t dt, int months, dt_adjust_t adjust);

Returns a date with the given numbers of months added. The parameter adjust defines the behaviour when the resulting month has fewer days than the day of the month for the given date.

(adjust = DT_EXCESS) If the resulting month has fewer days than the day of month for the given date, then the result is counted forward or backward into the next or previous month by the number of excessive days. Otherwise, the result has the same day of month as the given date. For example:

2012-01-31 + 1 month = 2012-03-02 *
2012-02-29 + 1 month = 2012-03-29

(adjust = DT_LIMIT) If the resulting month has fewer days than the day of month for the given date, then the result is the last day of the resulting month. Otherwise, the result has the same day of month as the given date. For example:

2012-01-31 + 1 month = 2012-02-29 *
2012-02-29 + 1 month = 2012-03-29

(adjust = DT_SNAP) If the given date is the last day of the month or if the resulting month has fewer days than the day of month for the given date, then the result is the last day of the resulting month. Otherwise, the result has the same day of month as the given date. For example:

2012-01-31 + 1 month = 2012-02-29 *
2012-02-29 + 1 month = 2012-03-31 *

dt_add_weekdays

dt_t dt_add_weekdays(dt_t dt, int weekdays);

Returns a date with the given number of weekdays (Monday through Friday) added.

dt_delta_yd

void dt_delta_yd(dt_t start, dt_t end, int *years, int *days);

Computes the difference between the given dates start and end in terms of years and days. If start is earlier than end, then the result is positive. If start is later than end, then the result is negative. The sign will be the same in each of years and days. The pointer parameters may be NULL for any of the results that are not required. For example the difference between 2012-140 and 2013-150 is 1 year and 10 days; the difference between 2012-160 and 2013-150 is 0 years and 356 days.

dt_delta_ymd

void dt_delta_ymd(dt_t start, dt_t end, int *years, int *months, int *days);

Computes the difference between the given dates start and end in terms of years, months and days. If start is earlier than end, then the result is positive. If start is later than end, then the result is negative. The sign will be the same in each of years, months and days. The pointer parameters may be NULL for any of the results that are not required. For example the difference between 2012-02-10 and 2013-10-20 is 1 year, 8 months and 10 days.

dt_delta_yqd

void dt_delta_yqd(dt_t start, dt_t end, int *years, int *quarters, int *days);

Computes the difference between the given dates start and end in terms of years, quarters and days. If start is earlier than end, then the result is positive. If start is later than end, then the result is negative. The sign will be the same in each of years, quarters and days. The pointer parameters may be NULL for any of the results that are not required. For example the difference between 2012-Q1-10 and 2013-Q4-20 is 1 year, 3 quarters and 10 days.

dt_delta_years

int dt_delta_years(dt_t start, dt_t end, bool complete);

Returns the difference between the given dates start and end in years. The parameter complete specifies whether or not only complete years should be calculated. A year is considered to be complete if the day of the year of the end date is greater than or equal to the day of the year of the start date. If start is earlier than end, then the result is positive. If start is later than end, then the result is negative. For example the difference between 2011-12-31 and 2012-01-01 is 1 when complete is false and 0 when complete is true.

dt_delta_quarters

int dt_delta_quarters(dt_t start, dt_t end, bool complete);

Returns the difference between the given dates start and end in quarters. The parameter complete specifies whether or not only complete years should be calculated. A quarter is considered to be complete if the day of the quarter of the end date is greater than or equal to the day of the quarter of the start date. If start is earlier than end, then the result is positive. If start is later than end, then the result is negative.

dt_delta_months

int dt_delta_months(dt_t start, dt_t end, bool complete);

Returns the difference between the given dates start and end in months. The parameter complete specifies whether or not only complete years should be calculated. A month is considered to be complete if the day of the month of the end date is greater than or equal to the day of the month of the start date. If start is earlier than end, then the result is positive. If start is later than end, then the result is negative. For example the difference between 2012-01-25 and 2012-02-01 is 1 when complete is false and 0 when complete is true; the delta between 2012-01-01 and 2012-01-31 is 0 regardless of complete.

dt_delta_weeks

int dt_delta_weeks(dt_t start, dt_t end);

Returns the difference between the given dates start and end in weeks. If start is earlier than end, then the result is positive. If start is later than end, then the result is negative.

dt_delta_weekdays

int dt_delta_weekdays(dt_t start, dt_t end, bool inclusive);

Returns the number of weekdays (Monday through Friday) between the given dates start and end. The parameter inclusive specifies whether the end date should be inclusive. If start is earlier than end, then the result is positive. If start is later than end, then the result is negative.

dt_parse_string

size_t dt_parse_string(const char *str, size_t len, dt_t *dtp);

dt_leap_year

bool dt_leap_year(int year);

Returns a boolean indicating whether or not the given year is a leap year.

dt_days_in_year

int dt_days_in_year(int year);

Returns the number of days in the given year (365-366).

dt_days_in_quarter

int dt_days_in_quarter(int year, int quarter);

Returns the number of days in the given quarter (90-92) within the given year. Returns 0 if the given quarter is out of range (1-4).

dt_days_in_month

int dt_days_in_month(int year, int month);

Returns the number of days in the given month (28-31) within the given year. Returns 0 if the given month is out of range (1-12).

dt_weeks_in_year

int dt_weeks_in_year(int year);

Returns the number of weeks in the given year (52-53).

TEST HARNESS

The unit tests is written in C using the Test Anything Protocol (TAP). Perl and the prove command (provided by Perl module Test::Harness) is required to run the harness. The version of Test::Harness must be equal to or greater than v3.23.

$ prove -V
TAP::Harness v3.23 and Perl v5.14.1

Installing Test::Harness

Install using the cpan client:

$ cpan install Test::Harness

Install using the source package (http://search.cpan.org/dist/Test-Harness/):

$ tar -zxf Test-Harness-3.25.tar.gz
$ cd Test-Harness-3.25
$ perl Makfile.PL
$ make
$ make test
$ sudo make install

Compiling and running the test harness:

$ make test

output:

t/yd.t ................ ok
t/ymd.t ............... ok
t/ymd_epochs.t ........ ok
t/yqd.t ............... ok
t/ywd.t ............... ok
t/tm.t ................ ok
t/easter_western.t .... ok
t/easter_orthodox.t ... ok
t/days_in_year.t ...... ok
t/days_in_month.t ..... ok
t/days_in_quarter.t ... ok
t/start_of_year.t ..... ok
t/start_of_quarter.t .. ok
t/start_of_month.t .... ok
t/start_of_week.t ..... ok
t/end_of_year.t ....... ok
t/end_of_quarter.t .... ok
t/end_of_month.t ...... ok
t/end_of_week.t ....... ok
t/next_dow.t .......... ok
t/prev_dow.t .......... ok
t/next_weekday.t ...... ok
t/prev_weekday.t ...... ok
t/nth_dow.t ........... ok
t/add_years.t ......... ok
t/add_quarters.t ...... ok
t/add_months.t ........ ok
t/add_weekdays.t ...... ok
t/delta_yd.t .......... ok
t/delta_ymd.t ......... ok
t/delta_yqd.t ......... ok
t/delta_weekdays.t .... ok
t/parse_string.t ...... ok
t/add_workdays.t ...... ok
t/delta_workdays.t .... ok
t/is_holiday.t ........ ok
t/is_workday.t ........ ok
t/adjust.t ............ ok
All tests successful.
Files=38, Tests=13181,  2 wallclock secs ( 1.14 usr  0.09 sys +  0.04 cusr  0.06 csys =  1.33 CPU)
Result: PASS

SUPPORT

Bugs / Feature Requests

Please report any bugs or feature requests through the issue tracker at https://github.com/chansen/c-dt/issues.

Source Code

This is open source software. The code repository is available for public review and contribution under the terms of the license.

https://github.com/chansen/c-dt

git clone https://github.com/chansen/c-dt.git

ACKNOWLEDGEMENTS

Easter algorithms by Al Petrofsky, San Mateo County, California, U.S.A. http://petrofsky.org/.

The TAP producer which is bundled with this library is written by Jake Gelbman https://github.com/zorgnax/libtap.

AUTHOR

Christian Hansen <chansen@cpan.org>

COPYRIGHT AND LICENSE

Copyright (c) 2012-2015 Christian Hansen

This is free software; you can redistribute it and/or modify it under the terms of The BSD 2-Clause License.