/*************************************************************************** * Copyright (C) 2005 by Nicolas PASCAL * * nicolas.pascal@icare.univ-lille1.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ /************************************************************************** * History : * * 3/08/05 : start * **************************************************************************/ #ifndef DATE_H #define DATE_H #define DATE_TEST 0 #include #include #include #include #include #include #include #include "tools.h" using namespace std; /** The maximum number of characters in the string returned by the get_time_str function */ static const int MAX_FORMATTED_STRING_SIZE=128; /** Bad date exception class */ class bad_date : public exception { public: bad_date() {} ; ~bad_date() throw() { ; }; virtual const char* what() const throw() { string m="bad_date : Sorry, the date you tried to entered is invalid"; return m.c_str(); }; }; /** Bad month exception : outside of range [1,12] */ class bad_month : public exception { int month; public: bad_month(const int month) : month(month){}; ~bad_month() throw() {}; virtual const char* what() const throw() { string m="bad_month : it must be in range [1,12], and you entered "+MyTools::to_string(month); return m.c_str(); }; }; class parse_date_error : public std::exception { public: parse_date_error(const string &date, const string &format):date(date),format(format) {}; ~parse_date_error() throw() {} ; virtual const char* what() const throw() { std::ostringstream oss; oss<<"parse_date_error : can't parse the date "< " << leap_sec << endl; } }; /** Manages the manipulation of dates. REM : - midnight is used with the convention "00:00:00" ( not 24:00:00 ) LIMITATION : The year must be more than 1970, because inside the class, all dates are converted into the UNIX epoch time. In the following documentation, this means "the date that is represented by this object" */ class Date { time_t epoch_time; /* Table of the leap seconds between TAI and UTC from the 1st of January 1972 at 00:00:00 each line is : ( , , TAI - UTC leap seconds ) source : ftp://hpiers.obspm.fr/iers/bul/bulc/UTC-TAI.history */ static vector < Epoch2Leap > utc_2_tai_leap_sec; public: // constant number of leap seconds between the TAI93 start ( 1st of January 1993 at 00:00:00 ) and the UTC start () static const int nsec_tai93_to_utc_start = 27; /** * Constructor using "human dates" * @param year the year * @param month the month * @param day the day * @param hour the hour * @param min the minutes * @param sec the seconds */ Date(int year = 1970, int month = 1, int day = 1, int hour = 0, int min = 0, int sec = 0); /** * constructor using UNIX epoch time * @param tm a time_t UNIX date */ Date(const time_t& tm); /** * constructor using UNIX epoch time, but with a double cast * @param tm a time_t UNIX date converted to a double */ Date( const double & tm ); /** Destructor */ ~Date() {} ; /** * @brief initialize the static table of UTC to TAI leap seconds. This method must updated */ static void init_leap_sec_table (); /** * @brief compute the number of leap seconds between a TAI93 and UTC time at the given date * @param d a date * @return */ static double get_tai93_leap_sec ( const Date &d ); /** * @brief compute the number of leap seconds between a TAI70 and UTC time at the given date * @param d a date * @return */ static double get_tai_leap_sec ( const Date &d ); /** Affectation operator @param d the Date */ Date &operator= (const Date &d); /** A time in seconds addition operator @param time a time in secs that must be added to this */ Date operator+ (const double &time); /** equality test operator @param d a Date */ bool operator== (const Date &d) const; /** unequality test operator @param d a Date */ bool operator!= (const Date &d) const; /** less or equal test operator @param d a Date */ bool operator<= (const Date &d) const; /** greater or equal test operator @param d a Date */ bool operator>= (const Date &d) const; /** less test operator @param d a Date */ bool operator< (const Date &d) const; /** greater test operator @param d a Date */ bool operator> (const Date &d) const; /** * @brief check is the date is the start of the UNIX epoch time (default) * @return true is the date is the 1970:01:01T00:00:00Z */ bool is_epoch_start( ) const {return epoch_time==0.;}; /** the number of seconds of this @return the seconds */ const int get_sec() const; /** the number of minutes of this @return the minutes */ const int get_min() const; /** the number of hours of this @return the hours */ const int get_hour() const; /** the number of the day of this @return the day number */ const int get_day() const; /** the number of the month of this @return the month number */ const int get_month() const; /** the year of this @return the year number */ const int get_year() const; /** the number of days passed since the start of year @return the number of days from year start */ const int get_yday() const; /** * @brief list the days between the start date and end date (included) as a vector of "YYYY_MM_DD" strings * @param start the start date * @param end the end date * @return a vector of Date representing the days between @a start and @a end */ static const vector get_days(const Date &start, const Date &end); /** return the number of days for the given month of the given year @param month the number of the month (1->12) @param year the number of the year, using christian numeration (ex : 2005) @return the number of days of the month */ static const int get_nb_day(const int &month,const int &year); /** return the day number spend since the start of year @param year the number of the year, using christian numeration (ex : 2005) @param month the number of the month (1->12) @param day the number of the day @return the number of days since the start of year */ static int get_day_number(const int &year,const int &month, int &day); /** get the day number range for a month. Rem : the 1st january has the number 0 (POSIX convention) @param year the year, using 4 digits (ex 2005) @param month the month number (0->11) @param first the number (from the start of year) of the 1st day of the month (0->365) @param last the number (from the start of year) of the last day of the month (0->365) */ static void get_day_range(const int &year,const int &month, int &first, int &last); /** return a string representing the month passed in parametre, using 2 digits. In other words, if the month if less than 10, it will return 0+the_number_of_the_month. If more than 10, it will just convert the in month into a string. @param _month the number of the month */ static const string get_month_string( const int _month ); /** check is the 2 dates are issued of the same day (same day; month and year) */ const bool is_the_same_day(const Date &d); /** set the time using a julian date (in float days since 1/1/-4712 at 12h00) @param julian_time the julian date in year */ void set_julian_time(const double &julian_time); /** convert the Date represented by this into a julian date. @return the julian date in days */ const double get_julian_time(); /** * @brief access to the time in sec using the TAI (International Atomic Time) convention : seconds from Jan. 1, 1993 * @return the time in sec since the 1993/01/01 */ const double get_TAI93_time() const ; /** * @brief set the date using a TAI time (number of seconds passed since the 1993/01/01) * @param TAI_time a time in TAI convention */ void set_TAI93_time(const double &TAI_time); /** * @brief access to the time in hour using the ECMWF convention (number of hours from 1900/01/01 at 00:00:00) * @return the time in hours since the 1900/01/01 at 00:00:00 */ const double get_ECMWF_time() const ; /** * @brief set the date using the ECMWF convention (number of hours from 1900/01/01 at 00:00:00) * @param time a time in hours since the 1900/01/01 at 00:00:00 */ void set_ECMWF_time(const double &time); /** build the date with the day number + the month number. @param _year the year (the real one, not from 1970 or stuff like this. ex : 2005) @param _month the month in range (1->12) @param _day the day in range (1->31) @param _hour the hour in range (0->23) @param _min the minutes in range (0->59) @param _sec the seconds in range (0->59). In fact 60 is possible du to the Posix norma, but it's preferable not to use it in this case. */ void set_date(const int &_year = 1970, const int& _month = 1, const int& _day = 1, const int& _hour = 0, const int& _min = 0, const int& _sec = 0); /** build the date using a formatted string. @param s the formatted string containing the date @param _format the format. See strptime documentation for format description */ void set_date_str(const string &s = "", const char * _format = ""); /** * @brief return the date as a formatted string * @param _format the format. See strftime documentation for format description */ const string get_date_str(const char * _format = ""); /** set the date using an epoch (ie UNIX) time (number of seconds passed since the 1970/01/01) @param _epoch_time a time in UNIX convention */ void set_epoch_time(const time_t& _epoch_time); /** * @brief return the date using the UNIX epoch time convention (number of seconds passed since the 1970/01/01) */ time_t get_epoch_time() const { return epoch_time; } /** print out the date */ void print() const; string to_string() const; /** * @brief return the date using the UNIX epoch time convention (number of seconds passed since the 1970/01/01) * @param s a string representing a date * @param _format a string formatter using the strptime convention * @return the number of seconds in UNIX EPOCH time convention */ static time_t get_epoch_time ( const char* s_date, const char * format ); friend std::ostream &operator<< (std::ostream &stream, const Date &date); }; #endif