bes  Updated for version 3.20.6
date_proc.cc
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of ff_handler a FreeForm API handler for the OPeNDAP
4 // DAP2 data server.
5 
6 // Copyright (c) 2005 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This is free software; you can redistribute it and/or modify it under the
10 // terms of the GNU Lesser General Public License as published by the Free
11 // Software Foundation; either version 2.1 of the License, or (at your
12 // option) any later version.
13 //
14 // This software is distributed in the hope that it will be useful, but
15 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 // License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 // These functions handle date translation between Julian and Gregorian
26 // formats. 8/12/93 jhrg
27 //
28 // This code was originally copied from one of the ACM's code libraries and
29 // used in the browsed image server. That version was written in C.
30 
31 
32 #include "config_ff.h"
33 
34 static char rcsid[]not_used = {
35  "$Id$" };
36 
37 #include <cassert>
38 
39 #include "Error.h"
40 
41 using namespace libdap;
42 
43 // You have to add one to days[1] if the year is a leap year. Since the month
44 // number in a Gregorian date is ones-based, fill element zero below to
45 // avoid gratuitous subtractions of the index value. Note that the fill
46 // value is never used. 9/4/98 jhrg
47 static int
48  days_arr[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
49 
52 int is_leap(int year)
53 {
54  return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
55 }
56 
59 double days_in_year(int year)
60 {
61  return is_leap(year) ? 366.0 : 365.0;
62 }
63 
64 static inline int days(int year, int month)
65 {
66  if (!(year > 0) || !(month > 0 && month < 13))
67  throw Error(malformed_expr, "Date year or month is bad.");
68 
69  if (month == 2 && is_leap(year))
70  return 29;
71  else
72  return days_arr[month];
73 }
74 
86 long julian_day(int year, int month, int day)
87 {
88  if (!(year > 0))
89  throw Error(malformed_expr, "A date's year must be greater the zero.");
90  if (!(month > 0 && month < 13))
91  throw Error(malformed_expr,
92  "A date's month must be between zero and thirteen.");
93 
94  if (!(day > 0 && day <= days(year, month)))
95  throw Error(malformed_expr,
96  "A date's day must be between zero and 28-31, depending on the month.");
97 
98  long jdn;
99 
100  jdn = (long) year * 367 + month * 275 / 9 - (year + (month > 2)) * 7 / 4
101  - ((year - (month < 3)) / 100 + 1) * 3 / 4 + day + 1721029L;
102 
103  return (jdn);
104 }
105 
121 void gregorian_date(double jd, int *year, int *month, int *day, int *hours,
122  int *minutes, double *seconds)
123 {
124  assert(jd> 0.0);
125 
126  long j = (long) jd;
127  double tmp, frac = jd - j;
128 
129  if (frac >= 0.5) {
130  frac = frac - 0.5;
131  j++;
132  }
133  else {
134  frac = frac + 0.5;
135  }
136 
137  j -= 1721119L;
138  *year = (4L * j - 1L) / 146097L;
139  j = 4L * j - 1L - 146097L * *year;
140  *day = j / 4L;
141  j = (4L * *day + 3L) / 1461L;
142  *day = 4L * *day + 3L - 1461L * j;
143  *day = (*day + 4L) / 4L;
144  *month = (5L * *day - 3L) / 153L;
145  *day = 5L * *day - 3 - 153L * *month;
146  *day = (*day + 5L) / 5L;
147  *year = 100L * *year + j;
148  if (*month < 10) {
149  *month += 3;
150  }
151  else {
152  *month -= 9;
153  *year += 1;
154  }
155  tmp = 3600.0 * (frac * 24.0);
156  *hours = (int) (tmp / 3600.0);
157  tmp = tmp - *hours * 3600.0;
158  *minutes = (int) (tmp / 60.0);
159  *seconds = tmp - *minutes * 60.0;
160 }
161 
169 int month_day_to_days(int year, int month, int day)
170 {
171  if (!(year > 0))
172  throw Error(malformed_expr, "A date's year must be greater the zero.");
173  if (!(month > 0 && month < 13))
174  throw Error(malformed_expr,
175  "A date's month must be between zero and thirteen.");
176 
177  if (!(day > 0 && day <= days(year, month)))
178  throw Error(malformed_expr,
179  "A date's day must be between zero and 28-31, depending on the month.");
180 
181  int ddd = day;
182 
183  while (--month)
184  ddd += days(year, month);
185 
186  return ddd;
187 }
188 
189 // Note this could be implemented using days_arr[] defined at the top of this
190 // file. 5/23/2001 jhrg
191 int days_in_month(int year, int month)
192 {
193  //int daysInYear;
194  int daysInMonth; // ... might want to remove the temporary
195  // variable and just return the value from
196  // the switch. Although the temp makes
197  // debugging easier. 5/23/2001 jhrg
198 
199  switch (month) {
200  case 1:
201  case 3:
202  case 5:
203  case 7:
204  case 8:
205  case 10:
206  case 12:
207  daysInMonth = 31;
208  break;
209  case 2:
210  //daysInYear = (year % 4) && !(year % 100) && (year % 400) ? 366 : 365;
211  daysInMonth = (is_leap(year)) ? 29 : 28;
212  break;
213  case 4:
214  case 6:
215  case 9:
216  case 11:
217  daysInMonth = 30;
218  break;
219  default:
220  // Added. 5/23/2001 jhrg
221  throw Error("Months must be numbered between 1 and 12 inclusive.");
222  break;
223  }
224  return daysInMonth;
225 }
226 
238 void days_to_month_day(int year, int ddd, int *month, int *day)
239 {
240  assert(year> 0);
241  assert(ddd> 0 && ddd <= 365 + is_leap(year));
242 
243  *month = 1;
244 
245  while (ddd > days(year, *month))
246  ddd -= days(year, (*month)++);
247 
248  *day = ddd;
249 }
250 
257 int dayofweek(double j)
258 {
259  long jd = (long) j;
260  if (j - jd >= 0.5)
261  jd++;
262 
263  return (jd + 1) % 7;
264 }
265 
libdap
Definition: BESDapFunctionResponseCache.h:35
Error