2 * Routines for date handling
3 * Copyright (C) 2010,2015,2018 Olly Betts
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 is_leap_year(int year
)
31 return (year
% 4 == 0 && (year
% 100 != 0 || year
% 400 == 0));
35 last_day(int year
, int month
)
37 static const unsigned char lastday
[13] = {
38 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
40 SVX_ASSERT(month
>= 1 && month
<= 12);
41 return (month
== 2 && is_leap_year(year
)) ? 29 : lastday
[month
];
45 days_since_1900(int y
, int m
, int d
)
47 static const int m_to_d
[12] = {
48 0 - (1900 * 365) - 461 + 365,
49 31 - (1900 * 365) - 461 + 365,
50 59 - (1900 * 365) - 461,
51 90 - (1900 * 365) - 461,
52 120 - (1900 * 365) - 461,
53 151 - (1900 * 365) - 461,
54 181 - (1900 * 365) - 461,
55 212 - (1900 * 365) - 461,
56 243 - (1900 * 365) - 461,
57 273 - (1900 * 365) - 461,
58 304 - (1900 * 365) - 461,
59 334 - (1900 * 365) - 461
63 return d
+ (y
* 365) + m_to_d
[m
- 1] + (y
/ 4) - (y
/ 100) + (y
/ 400);
67 ymd_from_days_since_1900(int days
, int * py
, int * pm
, int * pd
)
69 int g
, dg
, c
, dc
, b
, db
, a
, da
, y
, m
;
73 c
= (dg
/ 36524 + 1) * 3 / 4;
77 a
= (db
/ 365 + 1) * 3 / 4;
79 y
= g
* 400 + c
* 100 + b
* 4 + a
;
80 m
= (da
* 5 + 308) / 153;
83 *pd
= da
- (m
+ 2) * 153 / 5 + 123;
87 julian_date_from_days_since_1900(int days
)
89 int g
, dg
, c
, dc
, b
, db
, a
, da
, y
, m
;
96 c
= (dg
/ 36524 + 1) * 3 / 4;
100 a
= (db
/ 365 + 1) * 3 / 4;
102 y
= g
* 400 + c
* 100 + b
* 4 + a
;
103 m
= (da
* 5 + 308) / 153;
105 /* dys is days since 1900 for the start of the year y. */
106 dys
= (y
- 1900) * 365 - 460;
107 dys
+= ((y
- 1) / 4) - ((y
- 1) / 100) + ((y
- 1) / 400);
108 scale
= (is_leap_year(y
) ? 1 / 366.0 : 1 / 365.0);
109 return y
+ scale
* (days_in
- dys
);