1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
9 #ifndef anna_time_Date_hpp
10 #define anna_time_Date_hpp
12 #include <anna/core/RuntimeException.hpp>
13 #include <anna/core/mt/Mutex.hpp>
19 #include <anna/time/internal/Timezone.hpp>
28 //------------------------------------------------------------------------------
29 //---------------------------------------------------------------------- #define
30 //------------------------------------------------------------------------------
32 // Unix time reference: 01/01/1970 00:00:00 UTC
33 // NTP time reference: 01/01/1900 00:00:00 UTC
34 // -> 70 years have 2207520000 seconds.
35 // -> Between 1900 and 1970 there are 17 leap years: 1468800 seconds more (17 days)
36 // TOTAL DIFFERENCE = 2207520000 + 1468800 = 2208988800
37 #define TIMESTAMP_OFFSET_NTP1900_OVER_UNIX1970 2208988800U
38 //#define _2K38_EFFECT_LIMIT "20380119031407" // UTC
47 * Absolute time representation structs class manager.
48 * Allow any time assignment/extraction regarding any timezone.
49 * Uses shell TZ assignment or rely on system timezone configuration (in ubuntu, /etc/timezone
50 * stores the abbreviation and /etc/localtime keeps the timezone file from /usr/share/zoneinfo).
52 * The internal unix timestamp reamain constant and thedate representation depends on the
53 * configured timezone. Some store methods could specify a certain origin timezone, but the
54 * instance inner timezone won't be changed until the user want to do that.
60 * anna::time::functions::initialize();
61 * std::cout << "SystemTimezone: " << anna::time::functions::getSystemTimezone().asString() << std::endl;
63 * anna::time::Date myBirth ("CET");
64 * myBirth.store("19741219111500", "EET");
65 * std::cout << "myBirth: " << myBirth.asString() << std::endl;
67 * anna::time::Date same_moment_canary_island("GMT");
68 * same_moment_canary_island.store(myBirth.getUnixTimestamp());
69 * std::cout << "same_moment_canary_island: " << same_moment_canary_island.asString() << std::endl;
70 * myBirth.setTz("GMT");
71 * std::cout << "myBirth on GMT: " << myBirth.asString() << std::endl;
72 * std::cout << "EQUAL: same_moment_canary_island = " << same_moment_canary_island.yyyymmddHHmmss() << "; myBirth in context GMT = " << myBirth.yyyymmddHHmmss() << std::endl;
73 * same_moment_canary_island.setTz("CET");
74 * std::cout << "same_moment_canary_island on CET: " << same_moment_canary_island.asString() << std::endl;
75 * anna::time::Date birthday("EET");
76 * birthday.store(same_moment_canary_island.getTm(), "CET");
77 * std::cout << "EQUAL: birthday TS = " << birthday.getUnixTimestamp() << "; myBirth TS = " << myBirth.getUnixTimestamp() << std::endl;
78 * std::cout << "birthday EET = " << birthday.asString() << std::endl;
80 * std::cout << "Setting Local timezone ..." << std::endl;
81 * myBirth.setSystemTimezone();
82 * birthday.setSystemTimezone();
83 * std::cout << "EQUAL: birthday " << birthday.asString() << "; myBirth " << myBirth.asString() << std::endl;
84 * std::cout << "EQUAL: birthday (Local Timezone)= " << birthday.yyyymmddHHmmss() << "; myBirth (Local Timezone)= " << myBirth.yyyymmddHHmmss() << std::endl;
85 * std::cout << "myBirth TZ = " << myBirth.getTzAsString() << std::endl;
86 * std::cout << "birthday TZ = " << myBirth.getTzAsString() << std::endl;
88 * myBirth.setTz("GMT");
89 * std::cout << "myBirth in GMT = " << myBirth.yyyymmddHHmmss() << std::endl;
93 * SystemTimezone: <TZ unset\>
94 * myBirth: Thursday 19/12/1974 10:15:00 CET, isdst = 0 [Unix Timestamp: 156676500, Ntp Timestamp: 2365665300], System Timezone: <TZ unset\>
95 * same_moment_canary_island: Thursday 19/12/1974 09:15:00 GMT, isdst = 0 [Unix Timestamp: 156676500, Ntp Timestamp: 2365665300], System Timezone: <TZ unset\>
96 * myBirth on GMT: Thursday 19/12/1974 09:15:00 GMT, isdst = 0 [Unix Timestamp: 156676500, Ntp Timestamp: 2365665300], System Timezone: <TZ unset\>
97 * EQUAL: same_moment_canary_island = 19741219091500; myBirth in context GMT = 19741219091500
98 * same_moment_canary_island on CET: Thursday 19/12/1974 10:15:00 CET, isdst = 0 [Unix Timestamp: 156676500, Ntp Timestamp: 2365665300], System Timezone: <TZ unset\>
99 * EQUAL: birthday TS = 156676500; myBirth TS = 156676500
100 * birthday EET = Thursday 19/12/1974 11:15:00 EET, isdst = 0 [Unix Timestamp: 156676500, Ntp Timestamp: 2365665300], System Timezone: <TZ unset\>
101 * Setting Local timezone ...
102 * EQUAL: birthday Thursday 19/12/1974 10:15:00 <TZ unset\>, isdst = 0 [Unix Timestamp: 156676500, Ntp Timestamp: 2365665300], System Timezone: <TZ unset\>; myBirth Thursday 19/12/1974 10:15:00 <TZ unset\>, isdst = 0 [Unix Timestamp: 156676500, Ntp Timestamp: 2365665300], System Timezone: <TZ unset\>
103 * EQUAL: birthday (Local Timezone)= 19741219101500; myBirth (Local Timezone)= 19741219101500
104 * myBirth TZ = <TZ unset\>
105 * birthday TZ = <TZ unset\>
106 * myBirth in GMT = 19741219091500
112 /////////////////////////////////////////////////
113 // Key: Keep coherent all time representations //
114 /////////////////////////////////////////////////
117 Timezone a_tz; // timezone for this instance context
118 time_t a_timestamp; // unix timestamp
124 // sets the current date/time (time(NULL)) and provided TimeZone as described in constructor
125 void initialize(const char *TZ = NULL) throw();
127 // main refresh method regarding timestamp
128 void refresh(void) throw();
135 * Default Constructor
136 * @param TZ timezone for date/time representation. Default (NULL) assumes the system
137 * timezone configuration. Empty string will be interpreted as UTC timezone.
139 Date(const char *TZ = NULL);
144 Date(const Date & d) { *this = d; }
155 * Sets the current date/time (time(NULL)) and provided TimeZone as described in constructor
157 void setNow(const char *TZ = NULL) throw() { initialize(TZ); }
161 * Sets the provided timezone for date/time representation of the class instance.
162 * This method keeps invariant the unix timestamp, thus, the date representation
163 * will evolve depending on the configured timezone.
164 * @warning Be careful with incorrect TZ values because no error will be shown but
165 * dates could be misleading. The valid TZ could be seen with tzselect tool or
166 * directly looking at /usr/share/zoneinfo hierarchy.
168 * @param TZ timezone for date/time representation.
169 * Default (NULL) is the local host (user-supplied) timezone
170 * Empty string sets UTC0 (GMT, Greenwich)
171 * Use available timezones in /usr/share/zoneinfo; i.e.: Europe/Madrid, CET, etc.
172 * You can also use 'tzselect' helper, but that tool don't change the system
173 * timezone, only helps to know the valid TZ values and shows how to change
174 * the timezone settings if you would want to do that).
176 void setTz(const char *TZ = NULL) throw();
180 Sets the local host timezone (even if it is based on TZ or in /usr/share/zoneinfo)
182 void setSystemTimezone() throw();
186 * Sets date/time providing unix timestamp (seconds since 01-Jan-1970 GMT)
188 * @param unixTimestamp Time since 01-Jan-1970 GMT
190 void store(const time_t & unixTimestamp) throw();
191 void storeUnix(const time_t & unixTimestamp) throw() { store(unixTimestamp); }
195 * Sets date/time providing ntp timestamp (seconds since 01-Jan-1900 GMT)
197 * @param ntpTimestamp Time since 01-Jan-1900 GMT
199 void storeNtp(const unsigned int &ntpTimestamp) throw();
203 * Sets date/time from standard 'tm' struct and optional timezone
205 * @param date 'tm' struct date/time
206 * @param TZ timezone for date/time provided. Default (NULL) assumes the system
207 * timezone configuration. Empty string will be interpreted as UTC timezone.
209 void store(const struct tm &date, const char *TZ = NULL) throw(anna::RuntimeException);
213 * Sets date/time from string representation with certain provided format,
214 * and optional timezone
216 * @param stringDate Date/time string
217 * @param TZ timezone for date/time provided. Default (NULL) assumes the system
218 * timezone configuration. Empty string will be interpreted as UTC timezone.
219 * @param strptimeFormat Date/time string format for strptime primitive.
220 * See format syntax at http://man7.org/linux/man-pages/man3/strptime.3.html
222 void store(const std::string &stringDate, const char *TZ = NULL, const char *strptimeFormat = "%Y%m%d%H%M%S") throw(anna::RuntimeException);
223 //void store(const std::string &stringDate, const char *tz = NULL, const char *strptimeFormat = "%Y-%m-%d-%H-%M-%S") throw(anna::RuntimeException);
229 * @param d Source class instance
231 * @return Returns copied reference
233 Date & operator = (const Date &d);
242 * @param d1 First instance from Date class
243 * @param d2 Second instance from Date class
245 * @return Returns d1 == d2 comparison
247 friend bool operator == (const Date & d1, const Date & d2) {
248 return (d1.getUnixTimestamp() == d2.getUnixTimestamp());
254 * @param d1 First instance from Date class
255 * @param d2 Second instance from Date class
257 * @return Returns d1 != d2 comparison
259 friend bool operator != (const Date & d1, const Date & d2) {
260 return (d1.getUnixTimestamp() != d2.getUnixTimestamp());
266 * @param d1 First instance from Date class
267 * @param d2 Second instance from Date class
269 * @return Returns d1 <= d2 comparison (compare unix timestamp unix, ignore TZ)
271 friend bool operator <= (const Date & d1, const Date & d2) {
272 return (d1.getUnixTimestamp() <= d2.getUnixTimestamp());
278 * @param d1 First instance from Date class
279 * @param d2 Second instance from Date class
281 * @return Returns d1 >= d2 comparison (compare unix timestamp unix, ignore TZ)
283 friend bool operator >= (const Date & d1, const Date & d2) {
284 return (d1.getUnixTimestamp() >= d2.getUnixTimestamp());
289 * Gets context instance timezone information
291 * @return NULL if TZ is unset, or string for TZ environment variable
292 * (empty is allowed and use to be understood as UTC.
294 const char *getTz(void) const throw() { return (a_tz.unsetTZ() ? NULL:a_tz.getValue().c_str()); }
298 * Gets the context timezone as string
300 std::string getTzAsString() const throw() { return a_tz.asString(); }
304 * Gets 'tm' struct on the current timezone
306 * @return 'tm' struct on the current timezone
308 const struct tm & getTm(void) const throw() { return a_tm; }
311 * Gets the week day abbreviation: Sun, Mon, Tue, Wed, Thu, Fri, Sat
313 * @return Day of the week
315 const char *getDay(void) const throw();
319 * Gets 'yyyymmddHHmmss' representation for the current timezone
321 * @return Time/date on format 'yyyymmddHHmmss'
325 std::string yyyymmddHHmmss(void) const throw();
329 * Gets unix timestamp (01-Jan-1970 GMT)
331 * @return Seconds since 01-Jan-1970 GMT
333 const time_t & getUnixTimestamp(void) const throw() { return a_timestamp; }
337 * Gets ntp timestamp (01-Jan-1900 GMT)
339 * @return Seconds since 01-Jan-1900 GMT
341 unsigned int getNtpTimestamp(void) const throw() {
342 unsigned int ntp_timestamp = a_timestamp + TIMESTAMP_OFFSET_NTP1900_OVER_UNIX1970;
343 return ntp_timestamp;
348 * Class string representation
350 * @return String with class content
352 std::string asString(void) const throw();
356 * Class XML representation
358 * @return XML with class content
360 anna::xml::Node* asXML(anna::xml::Node* parent) const throw();