WSL/SLF GitLab Repository

Date.h 9.5 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
65
66
67
68
69
70
71
72
73
74
			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)
			DIN ///<DIN5008 format: DD.MM.YYYY HH:MM
		} 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;

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

		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);
90
		void setDate(const Date& in_date);
91
		void setDate(const double& julian_in, const double& in_timezone, const bool& in_dst=false);
92
		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);
93
94
		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);
95
		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);
96
97
		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);
98
99
100
101
102
		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);
103
104
105
106
107
		void setUndef(const bool& flag);

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

		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;
119
		void getDate(int& year, int& month, int& day, int& hour, int& minute, int& second, const bool& gmt=false) const;
120
		void getTime(int& hour_out, int& minute_out, const bool& gmt=false) const;
121
		void getTime(int& hour_out, int& minute_out, int& second_out, const bool& gmt=false) const;
122
123
		int getYear(const bool& gmt=false) const;

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

129
130
131
		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);
132
		static double parseTimeZone(const std::string& timezone_iso);
133

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

		//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;
147

148
149
150
		///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.
151
		///Please use the Duration type instead of Date for such calculations!
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
		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:
167
		double localToGMT(const double& in_julian) const;
168
		double GMTToLocal(const double& in_gmt_julian) const;
169
170
		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;
171
172
		long getJulianDayNumber(const int&, const int&, const int&) const;
		bool isLeapYear(const int&) const;
173
		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;
174

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

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

} //end namespace

#endif