WSL/SLF GitLab Repository

Date.h 9.57 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/***********************************************************************************/
/*  Copyright 2009 WSL Institute for Snow and Avalanche Research    SLF-DAVOS      */
/***********************************************************************************/
/* This file is part of MeteoIO.
    MeteoIO is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    MeteoIO 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 Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with MeteoIO.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __DATE_H__
#define __DATE_H__

#include <meteoio/IOExceptions.h>

#include <string>
#include <sstream>

26
//#define NEGATIVE_JULIAN
27
28
29
30
31
32
33
34
namespace mio {

/**
 * @class Date
 * @brief  A class to handle timestamps.
 * This class handles conversion between different time display formats (ISO, numeric) as well as different
 * time representation (julian date, modified julian date, etc). It also handles time zones as well as
 * very basic Daylight Saving Time (DST). Since the activation dates of DST are political and not technical,
35
 * it can not be automatically calculated. Therefore, it has to be provided by the caller: when the dst flag
36
37
 * is set, the dst time shift is automatically applied. When the dst flag ceases to be set, the dst time shift
 * is no longer applied. This is very crude, but please keep in mind that using DST for monitoring data is
38
39
 * usually a bad idea... Finally, we assume that dates are positive. If this would not be the case, this
 * class has to be recompiled with the proper define.
40
 *
41
 * Internally, the date is stored as true julian date in GMT.
42
 * The maximal precision is 1 second (however with the limitation that leap seconds are currently not handled).
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
 *
 * Please see Date::FORMATS for supported display formats and http://en.wikipedia.org/wiki/Julian_day for
 * the various date representation definitions. The following data representation are currently supported:
 * - julian date, see Date::getJulianDate
 * - modified julian date, see Date::getModifiedJulianDate
 * - truncated julian date, see Date::getTruncatedJulianDate
 * - Unix date, see Date::getUnixDate
 * - Excel date, see Date::getExcelDate
 *
 * @ingroup data_str
 * @author Mathias Bavay
 * @date 2010-04-15
 */

class Date {
	public:
		///Keywords for selecting the date formats
		typedef enum {
			ISO, ///< ISO 8601 extended format combined date: YYYY-MM-DDTHH:mm:SS (fields might be dropped, in the least to the most significant order)
62
			ISO_TZ, ///< ISO 8601 format (same as ISO) but with time zone specification
63
64
			FULL, ///< ISO 8601 followed by the julian date (in parenthesis)
			NUM, ///< ISO 8601 basic format date: YYYYMMDDHHmmSS (fields might be dropped, in the least to the most significant order)
65
66
			DIN, ///<DIN5008 format: DD.MM.YYYY HH:MM
			ISO_WEEK ///< ISO 8601 week date: YYYY-Www-D (for example: 2014-W41-1)
67
68
69
70
71
72
73
74
75
		} FORMATS;

		///Keywords for selecting rounding strategy
		typedef enum RND_TYPE {
			UP, ///< rounding toward highest absolute value
			DOWN, ///< rounding toward smallest absolute value
			CLOSEST ///< rounding toward closest
		} RND;

76
77
		static const int daysLeapYear[];
		static const int daysNonLeapYear[];
78
79
80
81
		static const double DST_shift;
		static const float MJD_offset;
		static const float Unix_offset;
		static const float Excel_offset;
82
		static const float Matlab_offset;
83
84
85
86
87
88
89
90

		Date();
		Date(const double& julian_in, const double& in_timezone, const bool& in_dst=false);
		Date(const int& year, const int& month, const int& day, const int& hour, const int& minute, const double& in_timezone, const bool& in_dst=false);
		Date(const time_t&, const bool& in_dst=false);

		void setFromSys();
		void setTimeZone(const double& in_timezone, const bool& in_dst=false);
91
		void setDate(const Date& in_date);
92
		void setDate(const double& julian_in, const double& in_timezone, const bool& in_dst=false);
93
		void setDate(const int& year, const int& month, const int& day, const int& hour, const int& minute, const double& in_timezone, const bool& in_dst=false);
94
95
		void setDate(const int& year, const int& month, const int& day, const int& hour, const int& minute, const int& second, const double& in_timezone, const bool& in_dst=false);
		void setDate(const int& year, const int& month, const int& day, const int& hour, const int& minute, const double& second, const double& in_timezone, const bool& in_dst=false);
96
		void setDate(const int& year, const unsigned int& month, const unsigned int& day, const unsigned int& hour, const unsigned int& minute, const double& in_timezone, const bool& in_dst=false);
97
98
		void setDate(const int& year, const unsigned int& month, const unsigned int& day, const unsigned int& hour, const unsigned int& minute, const unsigned int& second, const double& in_timezone, const bool& in_dst=false);
		void setDate(const int& year, const unsigned int& month, const unsigned int& day, const unsigned int& hour, const unsigned int& minute, const double& second, const double& in_timezone, const bool& in_dst=false);
99
100
101
102
103
		void setDate(const time_t& in_time, const bool& in_dst=false);
		void setModifiedJulianDate(const double& julian_in, const double& in_timezone, const bool& in_dst=false);
		void setUnixDate(const time_t& in_time, const bool& in_dst=false);
		void setExcelDate(const double excel_in, const double& in_timezone, const bool& in_dst=false);
		void setMatlabDate(const double excel_in, const double& in_timezone, const bool& in_dst=false);
104
105
106
107
108
		void setUndef(const bool& flag);

		bool isUndef() const;
		double getTimeZone() const;
		bool getDST() const;
109
		double getJulian(const bool& gmt=false) const;
110
111
		double getModifiedJulianDate(const bool& gmt=false) const;
		double getTruncatedJulianDate(const bool& gmt=false) const;
112
		time_t getUnixDate() const;
113
		double getExcelDate(const bool& gmt=false) const;
114
		double getMatlabDate(const bool& gmt=false) const;
115
116
117
118
119

		void getDate(double& julian_out, const bool& gmt=false) const;
		void getDate(int& year, int& month, int& day, const bool& gmt=false) const;
		void getDate(int& year, int& month, int& day, int& hour, const bool& gmt=false) const;
		void getDate(int& year, int& month, int& day, int& hour, int& minute, const bool& gmt=false) const;
120
		void getDate(int& year, int& month, int& day, int& hour, int& minute, int& second, const bool& gmt=false) const;
121
		void getTime(int& hour_out, int& minute_out, const bool& gmt=false) const;
122
		void getTime(int& hour_out, int& minute_out, int& second_out, const bool& gmt=false) const;
123
124
		int getYear(const bool& gmt=false) const;

125
126
		unsigned short getDayOfWeek(const bool& gmt=false) const;
		unsigned short getISOWeekNr(const bool& gmt=false) const;
127
		int getJulianDayNumber(const bool& gmt=false) const;
128
129
		bool isLeapYear() const;

130
131
132
		static double rnd(const double& julian, const unsigned int& precision, const RND& type=CLOSEST);
		void rnd(const unsigned int& precision, const RND& type=CLOSEST);
		static const Date rnd(const Date& indate, const unsigned int& precision, const RND& type=CLOSEST);
133
		static double parseTimeZone(const std::string& timezone_iso);
134

135
		static std::string printFractionalDay(const double& fractional);
136
		const std::string toString(FORMATS type, const bool& gmt=false) const;
137
138
139
		const std::string toString() const;
		friend std::iostream& operator<<(std::iostream& os, const Date& date);
		friend std::iostream& operator>>(std::iostream& is, Date& date);
140
141
142
143
144
145
146
147

		//Operator Prototypes
		bool operator==(const Date&) const;
		bool operator!=(const Date&) const;
		bool operator<(const Date&) const;
		bool operator<=(const Date&) const;
		bool operator>(const Date&) const;
		bool operator>=(const Date&) const;
148

149
150
151
		///Intervals arithmetic
		///Can be used to add an interval to an existing Date object.
		///Construct a Date object representing the interval e.g. Date(1.0) for 1 day and add that to another Date object.
152
		///Please use the Duration type instead of Date for such calculations!
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
		Date& operator+=(const Date&);
		Date& operator-=(const Date&);
		Date& operator+=(const double&);
		Date& operator-=(const double&);
		Date& operator*=(const double&);
		Date& operator/=(const double&);

		const Date operator+(const Date&) const;
		const Date operator-(const Date&) const;
		const Date operator+(const double&) const;
		const Date operator-(const double&) const;
		const Date operator*(const double&) const;
		const Date operator/(const double&) const;

	protected:
168
		double localToGMT(const double& in_julian) const;
169
		double GMTToLocal(const double& in_gmt_julian) const;
170
171
		double calculateJulianDate(const int& in_year, const int& in_month, const int& in_day, const int& in_hour, const int& in_minute, const double& i_second) const;
		void calculateValues(const double& i_julian, int& out_year, int& out_month, int& out_day, int& out_hour, int& out_minute, int& o_second) const;
172
173
		long getJulianDayNumber(const int&, const int&, const int&) const;
		bool isLeapYear(const int&) const;
174
		void plausibilityCheck(const int& in_year, const int& in_month, const int& in_day, const int& in_hour, const int& in_minute, const double& in_second) const;
175

176
		static const double epsilon;
177
178
		double timezone;
		double gmt_julian;
179
		int gmt_year, gmt_month, gmt_day, gmt_hour, gmt_minute, gmt_second;
180
		bool dst;
181
182
183
184
185
186
187
188
		bool undef;
};

typedef Date Duration; //so that later, we can implement a true Interval/Duration class

} //end namespace

#endif