PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
calcalcs.h
Go to the documentation of this file.
1 /*
2  The CalCalcs routines, a set of C-language routines to perform
3  calendar calculations.
4 
5  Version 1.0, released 7 January 2010
6 
7  Copyright (C) 2010 David W. Pierce, dpierce@ucsd.edu
8 
9  This program is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22 
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 
27 #define CALCALCS_VERSION_NUMBER 1.0
28 
29 struct cccalendar {
30  int sig;
31  char *name;
33 
34  int (*c_isleap) ( int, int * );
35  int (*c_date2jday) ( int, int, int, int * );
36  int (*c_jday2date) ( int, int *, int *, int * );
37  int (*c_dpm) ( int, int, int * );
38 
39  /* The following implement "mixed" calendars, for example, our standard
40  * civil calendar, which converts from Julian to Gregorian, with the
41  * last day of the Julian calendar being 4 Oct 1582 and the first day
42  * of the Gregorian calendar being 15 Oct 1582
43  */
44  int mixed;
46  int year_x, month_x, day_x; /* These are the transition Y,M,D, i.e., the FIRST DATE the LATER CAL is used */
47  int year_px, month_px, day_px; /* These are the DAY BEFORE the transition Y,M,D, i.e., the last date the earlier cal is used */
48  int jday_x; /* Julian day of the transition date */
49 };
50 
51 /* A "country code", which holds the 2-letter code (abbreviation) for the country or region,
52  * its long name, and the Y/M/D date that it transitioned from the Julian to Gregorian calendar
53  */
54 struct ccs_ccode {
55  char *code, *longname;
56  int year, month, day;
57 };
58 
59 typedef struct cccalendar calcalcs_cal;
60 typedef struct ccs_ccode ccs_country_code;
61 
62 /* =====================================================================================
63  * Here are all the services this library supplies
64  *
65  * -------------------------------------------------------------------------
66  * ccs_init_calendar : initialize a calendar. Valid passed arguments are
67  * one of the following strings:
68  * Standard, proleptic_Gregorian, proleptic_Julian, noleap (aka 365_day and no_leap), 360_day
69  *
70  * The "Standard" calendar transitions from the Julian to the Gregorian calendar,
71  * with the last day of the Julian calender being 1582-10-04 and the next day being
72  * the first day of the Gregorian calendar, with the date 1582-10-15. This "transition date"
73  * can be set to be the value used by various countries, or set to any arbitrary
74  * date, using routine "set_cal_xition_date", below.
75  */
76 calcalcs_cal *ccs_init_calendar( const char *calname );
77 
78 /*------------------------------------------------------------------------------
79  * Frees the storage previously allocated by ccs_init_calendar()
80  */
82 
83 /*--------------------------------------------------------------------------
84  * ccs_date2jday: turn a Y/M/D date into a (true) Julian day number. Note that
85  * a Julian day is not the day number of the year, but rather
86  * the integer day number starting from 1 on the day that would
87  * have been 1 Jan 4713 BC if the Julian calendar went back
88  * to that time.
89  */
90 int ccs_date2jday( calcalcs_cal *calendar, int year, int month, int day, int *jday );
91 
92 /*--------------------------------------------------------------------------
93  * ccs_jday2date: turn a (true) Julian day number into a calendar date.
94  */
95 int ccs_jday2date( calcalcs_cal *calendar, int jday, int *year, int *month, int *day );
96 
97 /*--------------------------------------------------------------------------
98  * ccs_isleap: determine if the specified year is a leap year in
99  * the specified calendar
100  */
101 int ccs_isleap( calcalcs_cal *calendar, int year, int *leap );
102 
103 /*--------------------------------------------------------------------------
104  * ccs_dpm: returns the days per month for the given year/month.
105  * Note that during the month that transitions from a Julian to a
106  * Gregorian calendar, this might be a strange number of days.
107  */
108 int ccs_dpm( calcalcs_cal *calendar, int year, int month, int *dpm );
109 
110 /*--------------------------------------------------------------------------
111  * ccs_date2doy: given a Y/M/D date, calculates the day number of the year, starting at 1 for
112  * January 1st.
113  */
114 int ccs_date2doy( calcalcs_cal *calendar, int year, int month, int day, int *doy );
115 
116 /*--------------------------------------------------------------------------
117  * ccs_doy2date: given a year and a day number in that year (with counting starting at 1 for
118  * Jan 1st), this returns the month and day of the month that the doy refers to.
119  */
120 int ccs_doy2date( calcalcs_cal *calendar, int year, int doy, int *month, int *day );
121 
122 /*--------------------------------------------------------------------------
123  * ccs_dayssince: Given a Y/M/D date in a specified calendar, and the number of days since
124  * that date, this returns the new Y/M/D date in a (possibly different) calendar.
125  *
126  * Note that specifying "zero" days since, and giving different calendars as the original
127  * and new calendars, essentially converts dates between calendars.
128  */
129 int ccs_dayssince( calcalcs_cal *calendar_orig, int year_orig, int month_orig, int day_orig,
130  int ndays_since, calcalcs_cal *calendar_new, int *year_new, int *month_new, int *day_new );
131 
132 /*--------------------------------------------------------------------------
133  * get/set_cal_xition_date: these routines set the transition date for a Standard
134  * calendar, which is the date that the Gregorian calendar was first used.
135  * Before that, it is assumed that the Julian calendar was used.
136  *
137  * Historically, this transition date varies by country and region. The
138  * variation can be extreme, and over the centuries country boundaries have
139  * changed, so this should be considered only the grossest approximation. For
140  * that matter, for several countries, different districts/regions converted
141  * at different times anyway, so actually doing a good job at this task is
142  * far beyond this library's capability. Nevertheless, this does give some
143  * basic simplified capabilities in this regard. And you can always set
144  * the routines to use an arbitrary transition date of your own calculation.
145  *
146  * How to use these routines:
147  *
148  * If you know the transition date you want to impose, simply call
149  * set_cal_xition_date with the specified transition date. The date
150  * specified is the FIRST date that the new (Gregorian) calendar was
151  * used. For exaple, in Italy, the Gregorian calendar was first used
152  * on 15 October 1582.
153  *
154  * If you don't know what transition date to use, there is a brief
155  * database with some APPROXIMATE dates of transition that can be accessed
156  * by calling get_cal_xition_date with a two-letter country code, corresponding
157  * to the internet suffix for the country. (As a special case, "US" is used
158  * for the United States of America.) If the routine returns 0, then the
159  * country code is recognized and the approximate transition date is returned
160  * in the passed parameters year, month, day. These should then be given to
161  * routine set_cal_xition_date to make that calendar use the specified
162  * transition date. If the get_cal_xition_date routine does not return 0,
163  * then there is no information on that country in the database.
164  *
165  * routine set_cal_xition_date returns 0 on success, and something other than
166  * 0 on an error. Errors include trying to set the transition date to an
167  * invalid date, or trying to set the transition date for any calendar
168  * other than the "Standard" calendar.
169  *
170  * The following country/region codes are recognized: AK (Alaska) 1867/10/18;
171  * AL (Albania) 1912/12/1; AT (Austria) 1583/10/16; BE (Belgium) 1582/12/25;
172  * BG (Bulgaria) 1916/4/1; CN (China) 1929/1/1; CZ (Czechoslovakia) 1584/1/17;
173  * DK (Denmark) 1700/3/1; NO (Norway) 1700/3/1; EG (Egypt) 1875/1/1;
174  * EE (Estonia) 1918/1/1; FI (Finland) 1753/3/1; FR (France) 1582/12/20;
175  * DE (Germany, note different states actually used different dates between
176  * 1583 and 1700!) 1583/11/22; UK (Great Britain and Dominions) 1752/9/14;
177  * GR (Greece) 1924/3/23; HU (Hungary) 1587/11/1; IT (Italy) 1582/10/15;
178  * JP (Japan) 1918/1/1; LV (Latvia) 1915/1/1; LT (Lithuania) 1915/1/1;
179  * LU (Luxemburg) 1582/12/15; NL (Netherlands, note Catholic regions
180  * transitioned in various dates of 1582/83, while Protestant regions
181  * transitioned in various dates of 1700/01) 1582/10/15; NO (Norway) 1700/3/1;
182  * PL (Poland) 1582/10/15; PT (Portugal) 1582/10/15; RO (Romania) 1919/4/14;
183  * ES (Spain) 1582/10/15; SE (Sweden) 1753/3/1; CH (Switzerland, note,
184  * varied bewteen 1584 and 1701 by Canton) 1584/1/22; TR (Turkey)
185  * 1927/1/1; YU (Yugoslavia) 1919/1/1; UK (Great Britain and Dominions) 1752/9/14;
186  * US (United States) 1752/9/14; SU (former Soviet Union) 1918/2/1;
187  * RU (Russia) 1918/2/1.
188  */
189 int ccs_set_xition_date( calcalcs_cal *calendar, int year, int month, int day );
190 int ccs_get_xition_date( const char *country_code, int *year, int *month, int *day );
191 
192 /*--------------------------------------------------------------------------
193  * calcalcs_err_str: return a static char * to an error string, given the error number
194  */
195 char *ccs_err_str( int error_code );
196 
197 #define CALCALCS_ERR_NO_YEAR_ZERO -10
198 #define CALCALCS_ERR_DATE_NOT_IN_CALENDAR -11
199 #define CALCALCS_ERR_INVALID_DAY_OF_YEAR -12
200 #define CALCALCS_ERR_NOT_A_MIXED_CALENDAR -13
201 #define CALCALCS_ERR_UNKNOWN_COUNTRY_CODE -14
202 #define CALCALCS_ERR_OUT_OF_RANGE -15
203 #define CALCALCS_ERR_NULL_CALENDAR -16
204 #define CALCALCS_ERR_INVALID_CALENDAR -17
205 
206 #ifdef __cplusplus
207 }
208 #endif
calcalcs_cal * ccs_init_calendar(const char *calname)
Definition: calcalcs.c:103
void ccs_free_calendar(calcalcs_cal *calendar)
Definition: calcalcs.c:1337
char * ccs_err_str(int error_code)
Definition: calcalcs.c:907
int ccs_dayssince(calcalcs_cal *calendar_orig, int year_orig, int month_orig, int day_orig, int ndays_since, calcalcs_cal *calendar_new, int *year_new, int *month_new, int *day_new)
Definition: calcalcs.c:665
int ccs_date2doy(calcalcs_cal *calendar, int year, int month, int day, int *doy)
Definition: calcalcs.c:488
int ccs_jday2date(calcalcs_cal *calendar, int jday, int *year, int *month, int *day)
Definition: calcalcs.c:413
int ccs_isleap(calcalcs_cal *calendar, int year, int *leap)
Definition: calcalcs.c:335
int ccs_doy2date(calcalcs_cal *calendar, int year, int doy, int *month, int *day)
Definition: calcalcs.c:575
int ccs_date2jday(calcalcs_cal *calendar, int year, int month, int day, int *jday)
Definition: calcalcs.c:441
int ccs_dpm(calcalcs_cal *calendar, int year, int month, int *dpm)
Definition: calcalcs.c:361
int ccs_set_xition_date(calcalcs_cal *calendar, int year, int month, int day)
Definition: calcalcs.c:874
int ccs_get_xition_date(const char *country_code, int *year, int *month, int *day)
Definition: calcalcs.c:807
static std::string calendar(const File *input_file, const Config &config, const Logger &log)
Definition: Time.cc:146
int(* c_jday2date)(int, int *, int *, int *)
Definition: calcalcs.h:36
struct cccalendar * late_cal
Definition: calcalcs.h:45
int sig
Definition: calcalcs.h:30
struct cccalendar * early_cal
Definition: calcalcs.h:45
int(* c_date2jday)(int, int, int, int *)
Definition: calcalcs.h:35
int mixed
Definition: calcalcs.h:44
int(* c_isleap)(int, int *)
Definition: calcalcs.h:34
int year_px
Definition: calcalcs.h:47
int(* c_dpm)(int, int, int *)
Definition: calcalcs.h:37
int ndays_leap
Definition: calcalcs.h:32
char * name
Definition: calcalcs.h:31
int jday_x
Definition: calcalcs.h:48
int day_px
Definition: calcalcs.h:47
int ndays_reg
Definition: calcalcs.h:32
int day_x
Definition: calcalcs.h:46
int month_x
Definition: calcalcs.h:46
int year_x
Definition: calcalcs.h:46
int month_px
Definition: calcalcs.h:47
int month
Definition: calcalcs.h:56
int day
Definition: calcalcs.h:56
char * longname
Definition: calcalcs.h:55
int year
Definition: calcalcs.h:56
char * code
Definition: calcalcs.h:55