1 /* Copyright (c) 2015, 2021, Oracle and/or its affiliates.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License, version 2.0,
5  as published by the Free Software Foundation.
6 
7  This program is also distributed with certain software (including
8  but not limited to OpenSSL) that is licensed under separate terms,
9  as designated in a particular file or component or in included license
10  documentation.  The authors of MySQL hereby grant you an additional
11  permission to link the program and your derivative works with the
12  separately licensed software that they have included with MySQL.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  GNU General Public License, version 2.0, for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
22 
23 
24 #ifndef _MYSQLX_DATETIME_H_
25 #define _MYSQLX_DATETIME_H_
26 
27 #include <string>
28 #include <stdint.h>
29 #include <ostream>
30 #include <ios>
31 #include <iomanip>
32 #include <sstream>
33 
34 namespace mysqlx
35 {
36   class Time
37   {
38   public:
Time()39     Time() : m_negate(false), m_hour(0), m_minutes(0), m_seconds(0),
40       m_useconds(0), m_valid(false)
41     {}
42 
43     Time(bool negate_,
44          uint32_t hour_,
45          uint8_t minutes_,
46          uint8_t seconds_,
47          uint32_t useconds_ = 0)
m_negate(negate_)48     : m_negate(negate_), m_hour(hour_), m_minutes(minutes_),
49       m_seconds(seconds_), m_useconds(useconds_), m_valid(true)
50     {
51       if (minutes_ > 59 || seconds_ > 59 || useconds_ >= 1000000)
52         m_valid = false;
53     }
54 
valid()55     bool valid() const
56     {
57       return m_valid;
58     }
59 
60     operator bool () const
61     {
62       return m_valid;
63     }
64 
negate()65     bool negate() const { return m_negate; }
66 
hour()67     uint32_t hour() const { return m_hour; }
minutes()68     uint8_t minutes() const { return m_minutes; }
seconds()69     uint8_t seconds() const { return m_seconds; }
useconds()70     uint32_t useconds() const { return m_useconds; }
71 
to_string()72     std::string to_string() const
73     {
74       std::stringstream ss;
75 
76       if (!valid())
77         return "";
78 
79       ss.fill('0');
80       ss <<  (negate() ? "-" : "")
81         << std::setw(2) << static_cast<int>(hour())
82         << ":" << std::setw(2) << static_cast<int>(minutes())
83         << ":" << std::setw(2) << static_cast<int>(seconds())
84         << us_to_str(useconds());
85 
86       return ss.str();
87     }
88 
us_to_str(uint32_t val)89     static std::string us_to_str(uint32_t val)
90     {
91       if (0 == val)
92         return "";
93 
94       std::stringstream ss;
95       ss << "." <<  val;
96       std::string result = ss.str();
97       size_t last = result.find_last_not_of('0') + 1;
98       result.erase(last);
99 
100       return result;
101     }
102 
103   private:
104     bool m_negate;
105     uint32_t m_hour;
106     uint8_t m_minutes;
107     uint8_t m_seconds;
108     uint32_t m_useconds;
109     bool m_valid;
110   };
111 
112 
113   class DateTime
114   {
115   public:
116     DateTime(uint16_t year_,
117              uint8_t month_,
118              uint8_t day_,
119 
120              uint8_t hour_ = 0xff,
121              uint8_t minutes_ = 0,
122              uint8_t seconds_ = 0,
123              uint32_t useconds_ = 0)
m_year(year_)124     : m_year(year_), m_month(month_), m_day(day_),
125     m_hour(hour_), m_minutes(minutes_), m_seconds(seconds_),
126     m_useconds(useconds_), m_valid(true)
127     {
128       if (year_ > 9999 || month_ > 12 || day_ > 31)
129         m_valid = false;
130       if (hour_ != 0xff)
131       {
132         if (hour_ > 23 || minutes_ > 59 || seconds_ > 59 || useconds_ >= 1000000)
133           m_valid = false;
134       }
135     }
136 
DateTime()137     DateTime() {}
138 
valid()139     bool valid() const
140     {
141       return m_valid;
142     }
143 
144     operator bool () const
145     {
146       return m_valid;
147     }
148 
has_time()149     bool has_time() const
150     {
151       return m_hour != 0xff;
152     }
153 
to_string()154     std::string to_string() const
155     {
156       if (!valid())
157         return "";
158 
159       std::stringstream ss;
160       ss.fill('0');
161 
162       ss << std::setw(4) << year() << "/"
163         << std::setw(2) << static_cast<int>(month()) << "/"
164         << std::setw(2) << static_cast<int>(day());
165 
166       if (has_time())
167       {
168         ss << " " << std::setw(2) << static_cast<int>(hour())
169           << ":" << std::setw(2) << static_cast<int>(minutes())
170           << ":" << std::setw(2) << static_cast<int>(seconds())
171           << Time::us_to_str(useconds());
172       }
173 
174       return ss.str();
175     }
176 
year()177     uint16_t year() const { return m_year; }
month()178     uint8_t month() const { return m_month; }
day()179     uint8_t day() const { return m_day; }
180 
hour()181     uint8_t hour() const { return m_hour; }
minutes()182     uint8_t minutes() const { return m_minutes; }
seconds()183     uint8_t seconds() const { return m_seconds; }
useconds()184     uint32_t useconds() const { return m_useconds; }
time()185     Time time() const { return Time(false, m_hour, m_minutes, m_seconds, m_useconds); }
186 
187   private:
188     uint16_t m_year;
189     uint8_t m_month;
190     uint8_t m_day;
191 
192     uint8_t m_hour;
193     uint8_t m_minutes;
194     uint8_t m_seconds;
195     uint32_t m_useconds;
196 
197     bool m_valid;
198   };
199 
200 
201   inline std::ostream & operator<<(std::ostream &os, const DateTime &v)
202   {
203     if (v)
204     {
205       os << v.to_string();
206     }
207     return os;
208   }
209 
210   inline std::ostream & operator<<(std::ostream &os, const Time &v)
211   {
212     if (v)
213     {
214       os << v.to_string();
215     }
216     return os;
217   }
218 }
219 
220 #endif
221