4 * Copyright (C) 2009 Andreas Waidler <arandes@programmers.at>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include <libdatetime/Date.hxx>
22 #include <libdatetime/Timestamp.hxx>
23 #include <libdatetime/Month.hxx>
24 #include <libdatetime/Year.hxx>
28 Date::Date(const Timestamp
& timestamp
)/*{{{*/
29 : _timestamp(timestamp
)
31 , _month(Month::January
, _year
.isLeapYear())
34 if (_timestamp
< Timestamp(0)) {
36 } else if (_timestamp
> 0) {
37 _calculatePostEpoch();
42 const Year
& Date::year() const/*{{{*/
48 const Month
& Date::month() const/*{{{*/
54 int Date::day() const/*{{{*/
60 Date::operator int() const/*{{{*/
66 void Date::incrementYear()/*{{{*/
72 void Date::decrementYear()/*{{{*/
78 void Date::incrementMonth()/*{{{*/
80 // We can't blindly increment the month since the year changes after
82 // This is scenario does only occur if the Epoch does not begin in
84 if (_month
== Month::December
) {
86 _month
= Month(Month::January
, _year
.isLeapYear());
93 void Date::decrementMonth()/*{{{*/
95 // See incrementMonth() for explanation.
96 if (_month
== Month::January
) {
98 _month
= Month(Month::December
, _year
.isLeapYear());
105 void Date::incrementDay()/*{{{*/
107 // The month has to be incremented if the last day of the month is
108 // reached and shall be incremented. This happens only when the Epoch
109 // does not start on the first of any month.
110 if (_month
.days() == _day
) {
119 void Date::decrementDay()/*{{{*/
121 // See incrementDay() for explanation.
124 _day
= _month
.days();
131 void Date::_calculatePreEpoch()/*{{{*/
133 unsigned int remainder
= 0 - _timestamp
;
135 // As long as there is at least the same amount of seconds remaining than
136 // this previous year had, substract the seconds of that year from the
137 // remainder and decrease the year number.
141 if (remainder
< _year
.seconds()) {
145 remainder
-= _year
.seconds();
148 // Calculate the month.
151 if (remainder
< _month
.seconds()) {
155 remainder
-= _month
.seconds();
158 // Calculate the day of the month.
159 while (remainder
>= 24 * 60 * 60) {
160 remainder
-= 24 * 60 * 60;
164 if (0 == remainder
) return;
166 // We have a day. But if there is at least one second left to substract,
167 // the day has to be decremented as the time of the days is 00:00.
169 _timestamp
-= 24 * 60 * 60;
171 // We have to substract the time from the initial timestamp to obtain the
172 // actual timestamp of this date.
173 _timestamp
+= remainder
;
177 void Date::_calculatePostEpoch()/*{{{*/
179 unsigned int remainder
= _timestamp
;
180 // Calculate the year. Note that it can also be altered in the loops below
183 // As long as there is at least the same amount of seconds remaining than
184 // this current year has, substract the seconds of this year from the
185 // remainder and adjust the year.
186 while (remainder
>= _year
.seconds()) {
187 remainder
-= _year
.seconds();
191 // Calculate the month.
192 while (remainder
>= _month
.seconds()) {
193 remainder
-= _month
.seconds();
197 // Calculate the day of the month.
198 while (remainder
>= 24 * 60 * 60) {
199 remainder
-= 24 * 60 * 60;
203 // The Date has been calculated. What remains are the seconds that have
204 // passed since 00:00 this day, aka "the time". We have to substract the
205 // time from the initial timestamp to obtain the actual timestamp of this
207 _timestamp
-= remainder
;
213 // Use no tabs at all; two spaces indentation; max. eighty chars per line.
214 // vim: et ts=2 sw=2 sts=2 tw=80 fdm=marker