36static char rcsid[] not_used =
"$Id$";
47#include <libdap/BaseType.h>
48#include <libdap/Str.h>
49#include <libdap/debug.h>
61#include <libdap/Error.h>
65static 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);
128 string s = extract_argument(arg);
136void 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)) {
159 _day_number = month_day_to_days(_year, _month, _day);
165 _day_number = _month;
166 days_to_month_day(_year, _day_number, &_month, &_day);
172void 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)) {
190 _day_number = month_day_to_days(_year, _month, _day);
194 else if (((pos1 != date.npos) && (pos2 == date.npos)) || (pos1 == pos2)) {
198 _day_number = month_day_to_days(_year, _month, _day);
202 else if ((pos1 == date.npos) && (date.size() == 4)) {
207 _day_number = month_day_to_days(_year, _month, _day);
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);
223void 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;
236 secs_in_year = days_in_year(_year) * seconds_per_day;
241 d_year_day = (secs_in_year * year_fraction) / seconds_per_day + 1;
242 i_year_day = (int) d_year_day;
247 d_hr_day = ((d_year_day - i_year_day) * seconds_per_day) / seconds_per_hour;
248 i_hr_day = (int) d_hr_day;
253 d_min_day = ((d_hr_day - i_hr_day) * seconds_per_hour) / seconds_per_minute;
254 i_min_day = (int) d_min_day;
259 d_sec_day = (d_min_day - i_min_day) * seconds_per_minute;
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) {
277 if (i_year_day == (days_in_year(_year) + 1)) {
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.size() == 4) {
304 parse_iso8601_time(date);
307 throw Error(malformed_expr,
"Could not recognize date format");
315 _day_number = day_num;
316 days_to_month_day(_year, _day_number, &_month, &_day);
329 _day_number = month_day_to_days(_year, _month, _day);
342 _day_number = month_day_to_days(_year, _month, _day);
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;
424double DODS_Date::fraction()
const
426 return _year + (_day_number - 1) / days_in_year(_year);
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);
487int 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;
friend int operator==(DODS_Date &d1, DODS_Date &d2)
Equality.
friend int operator<(DODS_Date &d1, DODS_Date &d2)
Less than.
friend int operator>=(DODS_Date &d1, DODS_Date &d2)
Greater than or equal.
friend int operator!=(DODS_Date &d1, DODS_Date &d2)
Inequality.
friend int operator>(DODS_Date &d1, DODS_Date &d2)
Greater than.
string get(date_format format=ymd) const
date_format format() const
friend int operator<=(DODS_Date &d1, DODS_Date &d2)
Less than or equal.