pops-core  0.9
PoPS (Pest or Pathogen Spread) Model Core C++ library
date.hpp
Go to the documentation of this file.
1 /*
2  * PoPS model - date manipulation
3  *
4  * Copyright (C) 2015-2020 by the authors.
5  *
6  * Authors: Zexi Chen (zchen22 ncsu edu)
7  * Anna Petrasova
8  * Chris Jones
9  *
10  * The code contained herein is licensed under the GNU General Public
11  * License. You may obtain a copy of the GNU General Public License
12  * Version 2 or later at the following locations:
13  *
14  * http://www.opensource.org/licenses/gpl-license.html
15  * http://www.gnu.org/copyleft/gpl.html
16  */
17 
18 #ifndef POPS_DATE_HPP
19 #define POPS_DATE_HPP
20 
21 #include <iostream>
22 #include <string>
23 #include <stdexcept>
24 
25 namespace pops {
26 
32 class Date
33 {
34 
35 private:
36  int year_;
37  int month_;
38  int day_;
39  int day_in_month[2][13] = {
40  {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
41  {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
42 
43 public:
44  Date(const Date& d) : year_(d.year_), month_(d.month_), day_(d.day_) {}
45  Date(int y, int m, int d) : year_(y), month_(m), day_(d) {}
46  Date(std::string date);
47  Date& operator=(const Date&) = default;
48  inline void increased_by_days(int num_days);
49  inline void increased_by_week();
50  inline void increased_by_month();
51  inline void add_day();
52  inline void add_days(unsigned n);
53  inline void subtract_day();
54  inline void subtract_days(unsigned n);
55  inline Date get_year_end();
56  inline Date get_next_year_end();
57  inline Date get_last_day_of_week();
58  inline Date get_last_day_of_month();
59  inline bool is_last_week_of_year();
60  inline bool is_last_month_of_year();
61  inline bool is_last_day_of_year();
62  inline bool is_last_day_of_month();
63  inline bool is_last_week_of_month();
64  inline bool is_leap_year();
65  inline std::string to_string();
66  int month() const
67  {
68  return month_;
69  }
70  int year() const
71  {
72  return year_;
73  }
74  int day() const
75  {
76  return day_;
77  }
78  inline int weeks_from_date(Date start);
79  inline friend std::ostream& operator<<(std::ostream& os, const Date& d);
80  inline friend bool operator>(const Date& d1, const Date& d2);
81  inline friend bool operator>=(const Date& d1, const Date& d2);
82  inline friend bool operator<(const Date& d1, const Date& d2);
83  inline friend bool operator<=(const Date& d1, const Date& d2);
84  inline friend bool operator==(const Date& d1, const Date& d2);
85  inline friend bool operator!=(const Date& d1, const Date& d2);
86 };
87 
96 Date::Date(std::string date)
97 {
98  size_t pos = date.find("-");
99  year_ = std::stoi(date.substr(0, pos));
100  date.erase(0, pos + 1);
101  pos = date.find("-");
102  month_ = std::stoi(date.substr(0, pos));
103  date.erase(0, pos + 1);
104  day_ = std::stoi(date);
105  if (month_ <= 0 || month_ > 12 || day_ > day_in_month[1][month_])
106  throw std::invalid_argument("Invalid date specified");
107 }
108 
109 std::ostream& operator<<(std::ostream& os, const Date& d)
110 {
111  os << d.year_ << '-' << d.month_ << '-' << d.day_;
112  return os;
113 }
114 
116 {
117  return Date(year_, 12, 31);
118 }
126 {
127  Date d = Date(*this);
128  d.increased_by_week();
129  d.day_--;
130  if (d.day_ == 0) {
131  d.month_--;
132  if (d.month_ == 0) {
133  d.year_--;
134  d.month_ = 12;
135  }
136  d.day_ = day_in_month[is_leap_year()][d.month_];
137  }
138  return d;
139 }
140 
145 {
146  if (this->is_leap_year())
147  return Date(year_, month_, day_in_month[1][month_]);
148  return Date(year_, month_, day_in_month[0][month_]);
149 }
150 
152 {
153  if (month_ == 12 && (day_ + 9) > 31)
154  return true;
155  return false;
156 }
157 
159 {
160  if (month_ == 12)
161  return true;
162  return false;
163 }
164 
166 {
167  if (month_ == 12 && day_ == 31)
168  return true;
169  return false;
170 }
171 
173 {
174  if (this->is_leap_year()) {
175  if ((day_ + 7) >= day_in_month[1][month_])
176  return true;
177  return false;
178  }
179  else {
180  if ((day_ + 7) >= day_in_month[0][month_])
181  return true;
182  return false;
183  }
184 }
185 
187 {
188  if (this->is_leap_year()) {
189  if (day_ == day_in_month[1][month_])
190  return true;
191  return false;
192  }
193  else {
194  if (day_ == day_in_month[0][month_])
195  return true;
196  return false;
197  }
198 }
199 
201 {
202  if (month_ == 1)
203  return Date(year_, 12, 31);
204  else
205  return Date(year_ + 1, 12, 31);
206 }
207 
209 {
210  if (year_ % 4 == 0 && (year_ % 100 != 0 || year_ % 400 == 0))
211  return true;
212  return false;
213 }
214 
215 bool operator>(const Date& d1, const Date& d2)
216 {
217  if (d1.year_ < d2.year_)
218  return false;
219  else if (d1.year_ > d2.year_)
220  return true;
221  else {
222  if (d1.month_ < d2.month_)
223  return false;
224  else if (d1.month_ > d2.month_)
225  return true;
226  else {
227  if (d1.day_ <= d2.day_)
228  return false;
229  else
230  return true;
231  }
232  }
233 }
234 
235 bool operator<=(const Date& d1, const Date& d2)
236 {
237  return !(d1 > d2);
238 }
239 
240 bool operator<(const Date& d1, const Date& d2)
241 {
242  if (d1.year_ > d2.year_)
243  return false;
244  else if (d1.year_ < d2.year_)
245  return true;
246  else {
247  if (d1.month_ > d2.month_)
248  return false;
249  else if (d1.month_ < d2.month_)
250  return true;
251  else {
252  if (d1.day_ >= d2.day_)
253  return false;
254  else
255  return true;
256  }
257  }
258 }
259 
260 bool operator>=(const Date& d1, const Date& d2)
261 {
262  return !(d1 < d2);
263 }
264 
265 bool operator==(const Date& d1, const Date& d2)
266 {
267  if (d1.year_ == d2.year_ && d1.month_ == d2.month_ && d1.day_ == d2.day_)
268  return true;
269  return false;
270 }
271 
272 bool operator!=(const Date& d1, const Date& d2)
273 {
274  if (d1 == d2)
275  return false;
276  return true;
277 }
287 void Date::increased_by_days(int num_days)
288 {
289  day_ += num_days;
290  if (this->is_leap_year()) {
291  if (month_ == 12 && day_ > (31 - (num_days + 1))) {
292  year_++;
293  month_ = 1;
294  day_ = 1;
295  }
296  if (day_ > day_in_month[1][month_]) {
297  day_ = day_ - day_in_month[1][month_];
298  month_++;
299  if (month_ > 12) {
300  year_++;
301  month_ = 1;
302  }
303  }
304  }
305  else {
306  if (month_ == 12 && day_ > (31 - num_days)) {
307  year_++;
308  month_ = 1;
309  day_ = 1;
310  }
311  if (day_ > day_in_month[0][month_]) {
312  day_ = day_ - day_in_month[0][month_];
313  month_++;
314  if (month_ > 12) {
315  year_++;
316  month_ = 1;
317  }
318  }
319  }
320 }
321 
328 {
329  day_ += 7;
330  if (this->is_leap_year()) {
331  if (month_ == 12 && day_ > 23) {
332  year_++;
333  month_ = 1;
334  day_ = 1;
335  }
336  if (day_ > day_in_month[1][month_]) {
337  day_ = day_ - day_in_month[1][month_];
338  month_++;
339  if (month_ > 12) {
340  year_++;
341  month_ = 1;
342  }
343  }
344  }
345  else {
346  if (month_ == 12 && day_ > 24) {
347  year_++;
348  month_ = 1;
349  day_ = 1;
350  }
351  if (day_ > day_in_month[0][month_]) {
352  day_ = day_ - day_in_month[0][month_];
353  month_++;
354  if (month_ > 12) {
355  year_++;
356  month_ = 1;
357  }
358  }
359  }
360 }
361 
363 {
364  month_ += 1;
365  if (month_ > 12) {
366  year_++;
367  month_ = 1;
368  }
369  if (this->is_leap_year()) {
370  if (day_ > day_in_month[1][month_]) {
371  day_ = day_in_month[1][month_];
372  }
373  }
374  else {
375  if (day_ > day_in_month[0][month_]) {
376  day_ = day_in_month[0][month_];
377  }
378  }
379 }
384 {
385  day_++;
386  if (day_ > day_in_month[is_leap_year()][month_]) {
387  day_ = 1;
388  month_++;
389  if (month_ > 12) {
390  year_++;
391  month_ = 1;
392  }
393  }
394 }
399 {
400  day_--;
401  if (day_ == 0) {
402  month_--;
403  if (month_ == 0) {
404  year_--;
405  month_ = 12;
406  }
407  day_ = day_in_month[is_leap_year()][month_];
408  }
409 }
413 void Date::add_days(unsigned n)
414 {
415  for (unsigned i = 0; i < n; i++)
416  this->add_day();
417 }
418 
422 void Date::subtract_days(unsigned n)
423 {
424  for (unsigned i = 0; i < n; i++)
425  this->subtract_day();
426 }
427 
437 {
438  int week = 0;
439  while (start <= *this) {
440  week++;
441  start.increased_by_week();
442  }
443  return week - 1;
444 }
445 
452 std::string Date::to_string()
453 {
454  std::string date = std::to_string(year_) + "-";
455  if (month_ < 10) {
456  date += "0" + std::to_string(month_) + "-";
457  }
458  else {
459  date += std::to_string(month_) + "-";
460  }
461  if (day_ < 10) {
462  date += "0" + std::to_string(day_);
463  }
464  else {
465  date += std::to_string(day_);
466  }
467  return date;
468 }
469 
473 class Season
474 {
475 public:
476  Season(int start, int end) : start_month_(start), end_month_(end) {}
482  inline bool month_in_season(int month) const
483  {
484  return month >= start_month_ && month <= end_month_;
485  }
486 
487 private:
488  int start_month_;
489  int end_month_;
490 };
491 
492 } // namespace pops
493 
494 #endif // POPS_DATE_HPP
pops::Date::is_last_month_of_year
bool is_last_month_of_year()
Definition: date.hpp:158
pops::Date::get_year_end
Date get_year_end()
Definition: date.hpp:115
pops::Date
Representation and manipulation of a date for the simulation.
Definition: date.hpp:32
pops::Date::to_string
std::string to_string()
Returns the current date as a string Will be replaced by C++20 format function.
Definition: date.hpp:452
pops::Date::get_last_day_of_week
Date get_last_day_of_week()
Assumes we call it on the first day of a week.
Definition: date.hpp:125
pops::operator!=
bool operator!=(const Date &d1, const Date &d2)
Definition: date.hpp:272
pops::operator==
bool operator==(const Date &d1, const Date &d2)
Definition: date.hpp:265
pops::Date::operator>
friend bool operator>(const Date &d1, const Date &d2)
Definition: date.hpp:215
pops::operator<=
bool operator<=(const Date &d1, const Date &d2)
Definition: date.hpp:235
pops::Date::is_last_week_of_month
bool is_last_week_of_month()
Definition: date.hpp:172
pops::Date::month
int month() const
Definition: date.hpp:66
pops::Date::Date
Date(const Date &d)
Definition: date.hpp:44
pops::operator>=
bool operator>=(const Date &d1, const Date &d2)
Definition: date.hpp:260
pops::Date::operator==
friend bool operator==(const Date &d1, const Date &d2)
Definition: date.hpp:265
pops::operator>
bool operator>(const Date &d1, const Date &d2)
Definition: date.hpp:215
pops::Date::operator<=
friend bool operator<=(const Date &d1, const Date &d2)
Definition: date.hpp:235
pops::Season
Holds beginning and end of a season and decides what is in season.
Definition: date.hpp:473
pops::Date::operator<<
friend std::ostream & operator<<(std::ostream &os, const Date &d)
Definition: date.hpp:109
pops::Date::increased_by_month
void increased_by_month()
Definition: date.hpp:362
pops::Date::is_last_day_of_year
bool is_last_day_of_year()
Definition: date.hpp:165
pops::Date::increased_by_days
void increased_by_days(int num_days)
Increases the date by the num_days (specified by the user) except on the last timestep of the year,...
Definition: date.hpp:287
pops::Date::get_next_year_end
Date get_next_year_end()
Definition: date.hpp:200
pops::Date::is_last_day_of_month
bool is_last_day_of_month()
Definition: date.hpp:186
pops::Date::day
int day() const
Definition: date.hpp:74
pops
Definition: cauchy_kernel.hpp:25
pops::Date::add_days
void add_days(unsigned n)
Adds N days to a date.
Definition: date.hpp:413
pops::Date::subtract_day
void subtract_day()
Subtract 1 day from a date.
Definition: date.hpp:398
pops::Date::is_last_week_of_year
bool is_last_week_of_year()
Definition: date.hpp:151
pops::Date::operator>=
friend bool operator>=(const Date &d1, const Date &d2)
Definition: date.hpp:260
pops::Date::subtract_days
void subtract_days(unsigned n)
Subtract N days from a date.
Definition: date.hpp:422
pops::Date::increased_by_week
void increased_by_week()
Increases the date by one week (7 days) except on the last week of the year, which is increased by 8 ...
Definition: date.hpp:327
pops::Date::year
int year() const
Definition: date.hpp:70
pops::Date::operator<
friend bool operator<(const Date &d1, const Date &d2)
Definition: date.hpp:240
pops::operator<
bool operator<(const Date &d1, const Date &d2)
Definition: date.hpp:240
pops::Date::Date
Date(int y, int m, int d)
Definition: date.hpp:45
pops::Date::get_last_day_of_month
Date get_last_day_of_month()
Compute the last day of a month.
Definition: date.hpp:144
pops::Season::Season
Season(int start, int end)
Definition: date.hpp:476
pops::Date::add_day
void add_day()
Adds 1 day to a date.
Definition: date.hpp:383
pops::Date::operator=
Date & operator=(const Date &)=default
pops::operator<<
std::ostream & operator<<(std::ostream &os, const Date &d)
Definition: date.hpp:109
pops::Date::is_leap_year
bool is_leap_year()
Definition: date.hpp:208
pops::Date::operator!=
friend bool operator!=(const Date &d1, const Date &d2)
Definition: date.hpp:272
pops::Date::weeks_from_date
int weeks_from_date(Date start)
Gets number of weeks between start date and this date.
Definition: date.hpp:436
pops::Season::month_in_season
bool month_in_season(int month) const
Decides if a month is in season or not.
Definition: date.hpp:482