36 static char rcsid[]
not_used =
"$Id$";
65 static string extract_argument(BaseType *arg)
68 if (arg->type() != dods_str_c)
69 throw Error(malformed_expr,
"The Projection function requires a DODS string-type argument.");
74 arg->buf2val((
void **) &sp);
75 string s = sp->c_str();
78 DBG(cerr <<
"s: " << s << endl);
82 return static_cast<Str*
>(arg)->value();
90 return _year > 0 && _month > 0 && _day > 0 && _julian_day > 0 && _day_number > 0 && _format !=
unknown_format;
96 _julian_day(0), _year(0), _month(0), _day(0), _day_number(0), _format(
unknown_format)
102 string s = extract_argument(arg);
118 set(year, month, day);
123 set(year, month, day, format);
128 string s = extract_argument(arg);
136 void DODS_Date::parse_integer_time(
string date)
139 istringstream iss(date.c_str());
147 pos1 = date.find(
"/");
148 pos2 = date.rfind(
"/");
149 if ((pos1 == date.npos) && (pos2 == date.npos)) {
150 string msg =
"I cannot understand the date string: ";
151 msg += date +
". I expected a date formatted like yyyy/mm/dd or yyyy/ddd.";
152 throw Error(malformed_expr, msg);
154 else if ((pos1 != pos2)) {
165 _day_number = _month;
172 void DODS_Date::parse_iso8601_time(
string date)
175 istringstream iss(date.c_str());
183 pos1 = date.find(
"-");
184 pos2 = date.rfind(
"-");
185 if ((pos1 != date.npos) && (pos2 != date.npos) && (pos1 != pos2)) {
194 else if (((pos1 != date.npos) && (pos2 == date.npos)) || (pos1 == pos2)) {
202 else if ((pos1 == date.npos) && (date.length() == 4)) {
211 string msg =
"I cannot understand the date string: ";
212 msg += date +
". I expected an iso8601 date (ccyy-mm-dd, ccyy-mm or ccyy).";
213 throw Error(malformed_expr, msg);
223 void DODS_Date::parse_fractional_time(
string dec_year)
226 double d_year_day, d_hr_day, d_min_day, d_sec_day;
227 int i_year, i_year_day, i_hr_day, i_min_day, i_sec_day;
231 double d_year = strtod(dec_year.c_str(), 0);
233 i_year = (int) d_year;
234 double year_fraction = d_year - i_year;
242 i_year_day = (int) d_year_day;
248 i_hr_day = (int) d_hr_day;
254 i_min_day = (int) d_min_day;
260 i_sec_day = (int) d_sec_day;
266 if ((d_sec_day - i_sec_day) >= .5) i_sec_day++;
268 if (i_sec_day == 60) {
271 if (i_min_day == 60) {
274 if (i_hr_day == 24) {
285 set(i_year, i_year_day);
293 if (date.find(
".") != string::npos) {
294 parse_fractional_time(date);
296 else if (date.find(
"/") != string::npos) {
297 parse_integer_time(date);
299 else if (date.find(
"-") != string::npos) {
300 parse_iso8601_time(date);
302 else if (date.length() == 4) {
304 parse_iso8601_time(date);
307 throw Error(malformed_expr,
"Could not recognize date format");
315 _day_number = day_num;
357 return d1._julian_day == d2._julian_day ? 1 : 0;
362 return d1._julian_day != d2._julian_day ? 1 : 0;
367 return d1._julian_day < d2._julian_day ? 1 : 0;
372 return d1._julian_day > d2._julian_day ? 1 : 0;
380 return d1._julian_day <= d2._julian_day ? 1 : 0;
389 return d1._julian_day >= d2._julian_day ? 1 : 0;
435 oss << _year <<
"/" << _day_number;
438 oss << _year <<
"/" << _month <<
"/" << _day;
442 oss << _year <<
"-" << setfill(
'0') << setw(2) << _month;
445 oss << _year <<
"-" << setfill(
'0') << setw(2) << _month <<
"-" << setfill(
'0') << setw(2) << _day;
454 throw Error(unknown_error,
"Invalid date format");
456 assert(
"Invalid date format" &&
false);
466 tm_rec.tm_mday = _day;
467 tm_rec.tm_mon = _month - 1;
468 tm_rec.tm_year = _year - 1900;
472 tm_rec.tm_isdst = -1;
474 return mktime(&tm_rec);
487 int main(
int argc,
char *argv[])
494 d1.
set((
string)argv[1]);
497 d1.
set(atoi(argv[1]), atoi(argv[2]));
500 d1.
set(atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
503 d1.
set(atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), (
date_format)atoi(argv[4]));
506 cerr <<
"Wrong number of args!" << endl;
511 cout <<
"True: d1 < epoc" << endl;
513 cout <<
"False: d1 < epoc" << endl;
516 cout <<
"True: d1 > epoc" << endl;
518 cout <<
"False: d1 > epoc" << endl;
521 cout <<
"True: d1 <= epoc" << endl;
523 cout <<
"False: d1 <= epoc" << endl;
526 cout <<
"True: d1 >= epoc" << endl;
528 cout <<
"False: d1 >= epoc" << endl;
531 cout <<
"True: d1 == epoc" << endl;
533 cout <<
"False: d1 == epoc" << endl;
536 cout <<
"True: d1 != epoc" << endl;
538 cout <<
"False: d1 != epoc" << endl;
540 cout <<
"YMD: " << d1.
get() << endl;
541 cout <<
"ISO8601: " << d1.
get(
iso8601) << endl;
542 cout <<
"YD: " << d1.
get(
yd) << endl;
543 cout <<
"Julian day: " << d1.
julian_day() << endl;
544 cout <<
"Seconds: " << d1.
unix_time() << endl;
int operator>(DODS_Date &d1, DODS_Date &d2)
time_t unix_time() const
Return the number of seconds since 00:00:00 UTC 1 Jan 1970.
int days_in_month(int year, int month)
int operator!=(DODS_Date &d1, DODS_Date &d2)
double days_in_year(int year)
How many days are in the given Gregorian year?
int month_day_to_days(int year, int month, int day)
Given the month and day numbers, return the days since the first of the year.
date_format format() const
void set(string date)
Parse the string and assign the value to this object.
int operator<=(DODS_Date &d1, DODS_Date &d2)
bool OK() const
Class invariant.
DODS_Date()
Create an empty date.
int operator>=(DODS_Date &d1, DODS_Date &d2)
const double seconds_per_day
Useful constant values.
const double seconds_per_hour
void days_to_month_day(int year, int ddd, int *month, int *day)
Given the day number of the year, return the month and day of the month.
int operator==(DODS_Date &d1, DODS_Date &d2)
const double seconds_per_minute
int main(int argc, char **argv)
date_format
Constants used to denote different supported date formats.
int operator<(DODS_Date &d1, DODS_Date &d2)
long julian_day(int year, int month, int day)
Given a gregorian date in year, month and day, return the Julian day number.
string get(date_format format=ymd) const
Get the string representation for this date.