Eazy Datetime Cpp
datetime.h
1 /*
2 MIT License
3 
4 Copyright (c) 2021 n700a
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24 
31 #ifndef _MY_DATETIME_
32 #define _MY_DATETIME_
33 
34 #include <string>
35 #include <sstream>
36 #include <iomanip>
37 #include <time.h>
38 #include <regex>
39 #include <vector>
40 #include <limits>
41 
42 #if defined(_WIN32) || defined(_WIN64)
43 #include <windows.h>
44 #endif
45 
46 #include "time_delta.h"
47 #include "unix_time.h"
48 #include "datetime_parser.h"
49 #include "datetime_constants.h"
50 #include "datetime_exceptions.h"
51 
52 namespace EZ
53 {
58  class Datetime
59  {
60  time_t m_unixTime = 0;
61  bool m_isUTC = false;
62  MyParser m_parser;
63 
64  public:
71  Datetime(const std::string &timestamp, const std::string &format, const bool &isUTC = false)
72  {
73  m_isUTC = isUTC;
74  setDateTime(timestamp, format);
75  }
76 
77  Datetime(const std::string &timestamp, const char *format, const bool &isUTC = false)
78  {
79  m_isUTC = isUTC;
80  setDateTime(timestamp, format);
81  }
82 
83  Datetime(const char *timestamp, const std::string &format, const bool &isUTC = false)
84  {
85  m_isUTC = isUTC;
86  setDateTime(timestamp, format);
87  }
88 
89  Datetime(const char *timestamp, const char *format, const bool &isUTC = false)
90  {
91  m_isUTC = isUTC;
92  setDateTime(timestamp, format);
93  }
94 
100  Datetime(const std::string &timestamp, const bool &isUTC = false)
101  {
102  m_isUTC = isUTC;
103  setDateTime(timestamp, DatetimeConstants::DEFAULT_INPUT_FORMAT);
104  }
105 
106  Datetime(const char *timestamp, const bool &isUTC = false)
107  {
108  m_isUTC = isUTC;
109  setDateTime(timestamp, DatetimeConstants::DEFAULT_INPUT_FORMAT);
110  }
111 
116  Datetime(struct tm datetime, const bool &isUTC = false)
117  {
118  m_isUTC = isUTC;
119  validateInput(datetime);
120  m_unixTime = MyTM::my_mktime(datetime, m_isUTC);
121  }
126  Datetime(const time_t &unixTime = 0, const bool &isUTC = false)
127  {
128  m_isUTC = isUTC;
129  validateInput(unixTime);
130  m_unixTime = unixTime;
131  }
132 
133  Datetime(const Datetime &original)
134  {
135  m_isUTC = original.m_isUTC;
136  m_unixTime = original.m_unixTime;
137  }
148  Datetime(const int &year, const int &mon, const int &day,
149  const int &hour, const int &min, const int &sec,
150  const bool &isUTC = false)
151  {
152  m_isUTC = isUTC;
153  struct tm datetime;
154  try
155  {
156  datetime.tm_year = year - DatetimeConstants::TM_BASE_YEAR;
157  datetime.tm_mon = mon - DatetimeConstants::MONTH_OFFSET;
158  datetime.tm_mday = day;
159  datetime.tm_hour = hour;
160  datetime.tm_min = min;
161  datetime.tm_sec = sec;
162  }
163  catch (...)
164  {
165  throw DatetimeException("ERROR: Failed to parse input to struct tm");
166  }
167  validateInput(datetime);
168  m_unixTime = MyTM::my_mktime(datetime, m_isUTC);
169  }
170 
171  ~Datetime()
172  {
173  }
174 
181  void setIsUTC(const bool &isUTC)
182  {
183  m_isUTC = isUTC;
184  }
190  bool isUTC() const
191  {
192  return m_isUTC;
193  }
194 
199  struct tm structTm() const
200  {
201  validateInput(m_unixTime);
202  return MyTM::my_mkStructTm(m_unixTime, m_isUTC);
203  }
210  std::string str() const
211  {
212  return m_parser.time2str(structTm());
213  }
220  std::string str(const std::string &format) const
221  {
222  return m_parser.time2str(structTm(), format);
223  }
230  std::string str(const char *format) const
231  {
232  return m_parser.time2str(structTm(), format);
233  }
234 
241  std::string datetime() const
242  {
243  return str();
244  }
252  std::string date() const
253  {
254  return str("%Y/%m/%d");
255  }
263  std::string timesOfday() const
264  {
265  return str("%H:%M:%S");
266  }
271  int sec() const
272  {
273  auto tmpTm = structTm();
274  return tmpTm.tm_sec;
275  }
280  int minute() const
281  {
282  auto tmpTm = structTm();
283  return tmpTm.tm_min;
284  }
289  int hour() const
290  {
291  auto tmpTm = structTm();
292  return tmpTm.tm_hour;
293  }
298  int day() const
299  {
300  auto tmpTm = structTm();
301  return tmpTm.tm_mday;
302  }
307  int month() const
308  {
309  auto tmpTm = structTm();
310  return tmpTm.tm_mon + DatetimeConstants::MONTH_OFFSET;
311  }
316  long year() const
317  {
318  auto tmpTm = structTm();
319  return tmpTm.tm_year + DatetimeConstants::TM_BASE_YEAR;
320  }
325  long long unixTime() const
326  {
327  return m_unixTime;
328  }
334  int daysOfWeek() const
335  {
336  auto tmpTm = structTm();
337  return tmpTm.tm_wday;
338  }
339  // TODO: ISO
344  // int weeksOfYear() const
345  // {
346  // auto tmpTm = structTm();
347  // return (tmpTm.tm_yday / 7) + 1;
348  // }
349 
356  std::string timezone() const
357  {
358  auto tmpTm = structTm();
359 #if defined(_WIN32) || defined(_WIN64)
360  TIME_ZONE_INFORMATION tzi;
361  GetTimeZoneInformation(&tzi);
362  std::stringstream ss;
363  long bias = tzi.Bias;
364  if (m_isUTC)
365  {
366  ss << "UTC";
367  }
368  else
369  {
370  ss << "(" << tzi.Bias << "min from UTC)";
371  }
372  return ss.str();
373 #else
374  return std::string(tmpTm.tm_zone);
375 #endif
376  }
384  int isDst() const
385  {
386  auto tmpTm = structTm();
387  return tmpTm.tm_isdst;
388  }
389 
396  static Datetime now(const bool &isUTC = false)
397  {
398  time_t unixTime = time(NULL);
399  return Datetime(unixTime, isUTC);
400  }
401 
406  static Datetime minimum(const bool &isUTC = false)
407  {
408  return Datetime(time_t(DatetimeConstants::MINIMUM_SEC), isUTC);
409  }
410 
415  //https://cpprefjp.github.io/reference/limits/numeric_limits/max.html
416  static Datetime maximum(const bool &isUTC = false)
417  {
418  return Datetime(DatetimeConstants::MAXIMUM_SEC, isUTC);
419  }
420 
426  std::vector<int> toVector() const
427  {
428  auto tmpTm = structTm();
429  return {
430  tmpTm.tm_year + DatetimeConstants::TM_BASE_YEAR,
431  tmpTm.tm_mon + DatetimeConstants::MONTH_OFFSET,
432  tmpTm.tm_mday,
433  tmpTm.tm_hour,
434  tmpTm.tm_min,
435  tmpTm.tm_sec};
436  }
437 
438  private:
442  void validateInput(const time_t &time) const
443  {
444  if (time < DatetimeConstants::MINIMUM_SEC)
445  {
446  std::stringstream ss;
447  ss << "Input time is out of range. minimum datetime is " << Datetime::minimum(m_isUTC).str() << std::endl;
448  throw DatetimeException(ss.str());
449  }
450 
451  if (time > DatetimeConstants::MAXIMUM_SEC)
452  {
453  std::stringstream ss;
454  ss << "Input time is out of range. maximum datetime is " << Datetime::maximum(m_isUTC).str() << std::endl;
455  throw DatetimeException(ss.str());
456  }
457  }
461  void validateInput(const struct tm &datetime) const
462  {
463  time_t tmp = MyTM::my_mktime(datetime, m_isUTC);
464  validateInput(tmp);
465  }
469  void setDateTime(const std::string &timestamp, const std::string &format)
470  {
471  struct tm tmpTm = m_parser.str2time(timestamp, format);
472  try
473  {
474  m_unixTime = MyTM::my_mktime(tmpTm, m_isUTC);
475  validateInput(m_unixTime);
476  }
477  catch (...)
478  {
479  std::stringstream ss;
480  ss << "ERROR: "
481  << "\"" << timestamp << "\""
482  << " is in illegal time range." << std::endl;
483  throw DatetimeException(ss.str());
484  }
485  }
486 
487  public:
492  Datetime operator+(const long long &right) const
493  {
494  struct tm time;
495  time_t unixTimeR = time_t(right);
496  time_t retSec = m_unixTime + unixTimeR;
497  return Datetime(retSec, m_isUTC);
498  }
503  Datetime operator+(const TimeDelta &right) const
504  {
505  return operator+(right.totalSeconds());
506  }
507 
508  Datetime operator-(const long long &right) const
509  {
510  return operator+(-right);
511  }
512  Datetime operator-(const TimeDelta &right) const
513  {
514  return operator+(-right.totalSeconds());
515  }
516 
517  Datetime &operator=(const Datetime &right_t)
518  {
519  m_isUTC = right_t.m_isUTC;
520  m_unixTime = right_t.m_unixTime;
521  return *this;
522  }
527  Datetime &operator+=(const long long &right)
528  {
529  time_t unixTimeR = time_t(right);
530  m_unixTime += unixTimeR;
531  return *this;
532  }
538  {
539  return operator+=(right.totalSeconds());
540  }
541 
542  Datetime &operator-=(const long long &right)
543  {
544  return operator+=(-right);
545  }
546  Datetime &operator-=(const TimeDelta &right)
547  {
548  return operator+=(-right.totalSeconds());
549  }
550  };
551 
552  std::ostream &operator<<(std::ostream &stream, const Datetime &time)
553  {
554  stream << time.str();
555  return stream;
556  };
557 
562  TimeDelta operator-(const Datetime &left, const Datetime &right)
563  {
564  time_t diffSec = left.unixTime() - right.unixTime();
565  return TimeDelta(diffSec);
566  }
567 
572  bool operator==(const Datetime &left, const Datetime &right)
573  {
574  auto diffSec = left - right;
575  return diffSec == 0;
576  }
577 
578  bool operator!=(const Datetime &left, const Datetime &right)
579  {
580  return !(left == right);
581  }
582 
583  bool operator<(const Datetime &left, const Datetime &right)
584  {
585  auto diffSec = left - right;
586  return diffSec < 0;
587  }
588 
589  bool operator>(const Datetime &left, const Datetime &right)
590  {
591  auto diffSec = left - right;
592  return diffSec > 0;
593  }
594 
595  bool operator<=(const Datetime &left, const Datetime &right)
596  {
597  return (left < right) || (left == right);
598  }
599 
600  bool operator>=(const Datetime &left, const Datetime &right)
601  {
602  return (left > right) || (left == right);
603  }
604 
605 }
606 #endif
Definition: datetime_exceptions.h:9
Datetime object.
Definition: datetime.h:59
Datetime(struct tm datetime, const bool &isUTC=false)
Definition: datetime.h:116
Datetime(const std::string &timestamp, const bool &isUTC=false)
Definition: datetime.h:100
std::string date() const
Definition: datetime.h:252
std::string str(const std::string &format) const
Definition: datetime.h:220
void setIsUTC(const bool &isUTC)
Definition: datetime.h:181
int isDst() const
Definition: datetime.h:384
int day() const
Definition: datetime.h:298
int daysOfWeek() const
Definition: datetime.h:334
int month() const
Definition: datetime.h:307
std::string datetime() const
Definition: datetime.h:241
std::string timesOfday() const
Definition: datetime.h:263
struct tm structTm() const
Definition: datetime.h:199
Datetime & operator+=(const TimeDelta &right)
Definition: datetime.h:537
long year() const
Definition: datetime.h:316
Datetime(const int &year, const int &mon, const int &day, const int &hour, const int &min, const int &sec, const bool &isUTC=false)
Definition: datetime.h:148
Datetime operator+(const TimeDelta &right) const
Definition: datetime.h:503
int sec() const
Definition: datetime.h:271
Datetime & operator+=(const long long &right)
Definition: datetime.h:527
int minute() const
Definition: datetime.h:280
Datetime(const std::string &timestamp, const std::string &format, const bool &isUTC=false)
Definition: datetime.h:71
std::vector< int > toVector() const
Definition: datetime.h:426
int hour() const
Definition: datetime.h:289
std::string timezone() const
Definition: datetime.h:356
bool isUTC() const
Definition: datetime.h:190
static Datetime now(const bool &isUTC=false)
Definition: datetime.h:396
Datetime(const time_t &unixTime=0, const bool &isUTC=false)
Definition: datetime.h:126
Datetime operator+(const long long &right) const
Definition: datetime.h:492
static Datetime minimum(const bool &isUTC=false)
Definition: datetime.h:406
static Datetime maximum(const bool &isUTC=false)
Definition: datetime.h:416
std::string str() const
Definition: datetime.h:210
std::string str(const char *format) const
Definition: datetime.h:230
long long unixTime() const
Definition: datetime.h:325
TimeDelta object.
Definition: time_delta.h:19
long long totalSeconds() const
Definition: time_delta.h:94