1 // ANNA - Anna is Not Nothingness Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // http://redmine.teslayout.com/projects/anna-suite
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
17 // * Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
37 #ifndef anna_time_Date_hpp
38 #define anna_time_Date_hpp
40 #include <anna/core/RuntimeException.hpp>
41 #include <anna/core/mt/Mutex.hpp>
47 #include <anna/time/internal/Timezone.hpp>
56 //------------------------------------------------------------------------------
57 //---------------------------------------------------------------------- #define
58 //------------------------------------------------------------------------------
60 // Unix time reference: 01/01/1970 00:00:00 UTC
61 // NTP time reference: 01/01/1900 00:00:00 UTC
62 // -> 70 years have 2207520000 seconds.
63 // -> Between 1900 and 1970 there are 17 leap years: 1468800 seconds more (17 days)
64 // TOTAL DIFFERENCE = 2207520000 + 1468800 = 2208988800
65 #define TIMESTAMP_OFFSET_NTP1900_OVER_UNIX1970 2208988800U
66 //#define _2K38_EFFECT_LIMIT "20380119031407" // UTC
75 * Absolute time representation structs class manager.
76 * Allow any time assignment/extraction regarding any timezone.
77 * Uses shell TZ assignment or rely on system timezone configuration (in ubuntu, /etc/timezone
78 * stores the abbreviation and /etc/localtime keeps the timezone file from /usr/share/zoneinfo).
80 * The internal unix timestamp reamain constant and thedate representation depends on the
81 * configured timezone. Some store methods could specify a certain origin timezone, but the
82 * instance inner timezone won't be changed until the user want to do that.
88 * anna::time::functions::initialize();
89 * std::cout << "SystemTimezone: " << anna::time::functions::getSystemTimezone().asString() << std::endl;
91 * anna::time::Date myBirth ("CET");
92 * myBirth.store("19741219111500", "EET");
93 * std::cout << "myBirth: " << myBirth.asString() << std::endl;
95 * anna::time::Date same_moment_canary_island("GMT");
96 * same_moment_canary_island.store(myBirth.getUnixTimestamp());
97 * std::cout << "same_moment_canary_island: " << same_moment_canary_island.asString() << std::endl;
98 * myBirth.setTz("GMT");
99 * std::cout << "myBirth on GMT: " << myBirth.asString() << std::endl;
100 * std::cout << "EQUAL: same_moment_canary_island = " << same_moment_canary_island.yyyymmddHHmmss() << "; myBirth in context GMT = " << myBirth.yyyymmddHHmmss() << std::endl;
101 * same_moment_canary_island.setTz("CET");
102 * std::cout << "same_moment_canary_island on CET: " << same_moment_canary_island.asString() << std::endl;
103 * anna::time::Date birthday("EET");
104 * birthday.store(same_moment_canary_island.getTm(), "CET");
105 * std::cout << "EQUAL: birthday TS = " << birthday.getUnixTimestamp() << "; myBirth TS = " << myBirth.getUnixTimestamp() << std::endl;
106 * std::cout << "birthday EET = " << birthday.asString() << std::endl;
108 * std::cout << "Setting Local timezone ..." << std::endl;
109 * myBirth.setSystemTimezone();
110 * birthday.setSystemTimezone();
111 * std::cout << "EQUAL: birthday " << birthday.asString() << "; myBirth " << myBirth.asString() << std::endl;
112 * std::cout << "EQUAL: birthday (Local Timezone)= " << birthday.yyyymmddHHmmss() << "; myBirth (Local Timezone)= " << myBirth.yyyymmddHHmmss() << std::endl;
113 * std::cout << "myBirth TZ = " << myBirth.getTzAsString() << std::endl;
114 * std::cout << "birthday TZ = " << myBirth.getTzAsString() << std::endl;
116 * myBirth.setTz("GMT");
117 * std::cout << "myBirth in GMT = " << myBirth.yyyymmddHHmmss() << std::endl;
121 * SystemTimezone: <TZ unset\>
122 * myBirth: Thursday 19/12/1974 10:15:00 CET, isdst = 0 [Unix Timestamp: 156676500, Ntp Timestamp: 2365665300], System Timezone: <TZ unset\>
123 * same_moment_canary_island: Thursday 19/12/1974 09:15:00 GMT, isdst = 0 [Unix Timestamp: 156676500, Ntp Timestamp: 2365665300], System Timezone: <TZ unset\>
124 * myBirth on GMT: Thursday 19/12/1974 09:15:00 GMT, isdst = 0 [Unix Timestamp: 156676500, Ntp Timestamp: 2365665300], System Timezone: <TZ unset\>
125 * EQUAL: same_moment_canary_island = 19741219091500; myBirth in context GMT = 19741219091500
126 * 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\>
127 * EQUAL: birthday TS = 156676500; myBirth TS = 156676500
128 * birthday EET = Thursday 19/12/1974 11:15:00 EET, isdst = 0 [Unix Timestamp: 156676500, Ntp Timestamp: 2365665300], System Timezone: <TZ unset\>
129 * Setting Local timezone ...
130 * 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\>
131 * EQUAL: birthday (Local Timezone)= 19741219101500; myBirth (Local Timezone)= 19741219101500
132 * myBirth TZ = <TZ unset\>
133 * birthday TZ = <TZ unset\>
134 * myBirth in GMT = 19741219091500
140 /////////////////////////////////////////////////
141 // Key: Keep coherent all time representations //
142 /////////////////////////////////////////////////
145 Timezone a_tz; // timezone for this instance context
146 time_t a_timestamp; // unix timestamp
152 // sets the current date/time (time(NULL)) and provided TimeZone as described in constructor
153 void initialize(const char *TZ = NULL) throw();
155 // main refresh method regarding timestamp
156 void refresh(void) throw();
163 * Default Constructor
164 * @param TZ timezone for date/time representation. Default (NULL) assumes the system
165 * timezone configuration. Empty string will be interpreted as UTC timezone.
167 Date(const char *TZ = NULL);
172 Date(const Date & d) { *this = d; }
183 * Sets the current date/time (time(NULL)) and provided TimeZone as described in constructor
185 void setNow(const char *TZ = NULL) throw() { initialize(TZ); }
189 * Sets the provided timezone for date/time representation of the class instance.
190 * This method keeps invariant the unix timestamp, thus, the date representation
191 * will evolve depending on the configured timezone.
192 * @warning Be careful with incorrect TZ values because no error will be shown but
193 * dates could be misleading. The valid TZ could be seen with tzselect tool or
194 * directly looking at /usr/share/zoneinfo hierarchy.
196 * @param TZ timezone for date/time representation.
197 * Default (NULL) is the local host (user-supplied) timezone
198 * Empty string sets UTC0 (GMT, Greenwich)
199 * Use available timezones in /usr/share/zoneinfo; i.e.: Europe/Madrid, CET, etc.
200 * You can also use 'tzselect' helper, but that tool don't change the system
201 * timezone, only helps to know the valid TZ values and shows how to change
202 * the timezone settings if you would want to do that).
204 void setTz(const char *TZ = NULL) throw();
208 Sets the local host timezone (even if it is based on TZ or in /usr/share/zoneinfo)
210 void setSystemTimezone() throw();
214 * Sets date/time providing unix timestamp (seconds since 01-Jan-1970 GMT)
216 * @param unixTimestamp Time since 01-Jan-1970 GMT
218 void store(const time_t & unixTimestamp) throw();
219 void storeUnix(const time_t & unixTimestamp) throw() { store(unixTimestamp); }
223 * Sets date/time providing ntp timestamp (seconds since 01-Jan-1900 GMT)
225 * @param ntpTimestamp Time since 01-Jan-1900 GMT
227 void storeNtp(const unsigned int &ntpTimestamp) throw();
231 * Sets date/time from standard 'tm' struct and optional timezone
233 * @param date 'tm' struct date/time
234 * @param TZ timezone for date/time provided. Default (NULL) assumes the system
235 * timezone configuration. Empty string will be interpreted as UTC timezone.
237 void store(const struct tm &date, const char *TZ = NULL) throw(anna::RuntimeException);
241 * Sets date/time from string representation with certain provided format,
242 * and optional timezone
244 * @param stringDate Date/time string
245 * @param TZ timezone for date/time provided. Default (NULL) assumes the system
246 * timezone configuration. Empty string will be interpreted as UTC timezone.
247 * @param strptimeFormat Date/time string format for strptime primitive.
248 * See format syntax at http://man7.org/linux/man-pages/man3/strptime.3.html
250 void store(const std::string &stringDate, const char *TZ = NULL, const char *strptimeFormat = "%Y%m%d%H%M%S") throw(anna::RuntimeException);
251 //void store(const std::string &stringDate, const char *tz = NULL, const char *strptimeFormat = "%Y-%m-%d-%H-%M-%S") throw(anna::RuntimeException);
257 * @param d Source class instance
259 * @return Returns copied reference
261 Date & operator = (const Date &d);
270 * @param d1 First instance from Date class
271 * @param d2 Second instance from Date class
273 * @return Returns d1 == d2 comparison
275 friend bool operator == (const Date & d1, const Date & d2) {
276 return (d1.getUnixTimestamp() == d2.getUnixTimestamp());
282 * @param d1 First instance from Date class
283 * @param d2 Second instance from Date class
285 * @return Returns d1 != d2 comparison
287 friend bool operator != (const Date & d1, const Date & d2) {
288 return (d1.getUnixTimestamp() != d2.getUnixTimestamp());
294 * @param d1 First instance from Date class
295 * @param d2 Second instance from Date class
297 * @return Returns d1 <= d2 comparison (compare unix timestamp unix, ignore TZ)
299 friend bool operator <= (const Date & d1, const Date & d2) {
300 return (d1.getUnixTimestamp() <= d2.getUnixTimestamp());
306 * @param d1 First instance from Date class
307 * @param d2 Second instance from Date class
309 * @return Returns d1 >= d2 comparison (compare unix timestamp unix, ignore TZ)
311 friend bool operator >= (const Date & d1, const Date & d2) {
312 return (d1.getUnixTimestamp() >= d2.getUnixTimestamp());
317 * Gets context instance timezone information
319 * @return NULL if TZ is unset, or string for TZ environment variable
320 * (empty is allowed and use to be understood as UTC.
322 const char *getTz(void) const throw() { return (a_tz.unsetTZ() ? NULL:a_tz.getValue().c_str()); }
326 * Gets the context timezone as string
328 std::string getTzAsString() const throw() { return a_tz.asString(); }
332 * Gets 'tm' struct on the current timezone
334 * @return 'tm' struct on the current timezone
336 const struct tm & getTm(void) const throw() { return a_tm; }
339 * Gets the week day abbreviation: Sun, Mon, Tue, Wed, Thu, Fri, Sat
341 * @return Day of the week
343 const char *getDay(void) const throw();
347 * Gets 'yyyymmddHHmmss' representation for the current timezone
349 * @return Time/date on format 'yyyymmddHHmmss'
353 std::string yyyymmddHHmmss(void) const throw();
357 * Gets unix timestamp (01-Jan-1970 GMT)
359 * @return Seconds since 01-Jan-1970 GMT
361 const time_t & getUnixTimestamp(void) const throw() { return a_timestamp; }
365 * Gets ntp timestamp (01-Jan-1900 GMT)
367 * @return Seconds since 01-Jan-1900 GMT
369 unsigned int getNtpTimestamp(void) const throw() {
370 unsigned int ntp_timestamp = a_timestamp + TIMESTAMP_OFFSET_NTP1900_OVER_UNIX1970;
371 return ntp_timestamp;
376 * Class string representation
378 * @return String with class content
380 std::string asString(void) const throw();
384 * Class XML representation
386 * @return XML with class content
388 anna::xml::Node* asXML(anna::xml::Node* parent) const throw();