TECA
The Toolkit for Extreme Climate Analysis
teca_calendar_util.h
Go to the documentation of this file.
1 #ifndef teca_calendar_h
2 #define teca_calendar_h
3 
4 /// @file
5 
6 #include "teca_variant_array.h"
7 #include "teca_metadata.h"
8 
9 #include <string>
10 #include <ostream>
11 #include <cstring>
12 #include <memory>
13 
14 /// Codes dealing with calendaring
16 {
17 
18 /** @name Gregorian calendar
19  * functions for date computations in gregorian calendar. to use convert the
20  * origin to a gergorian_number do the calculation and convert the number back
21  * into a date useing date_from_gregorian_number. for details about the math
22  * and an explanation of the errors see
23  * http://alcor.concordia.ca/~gpkatch/gdate-algorithm.html
24  */
25 ///@{
26 /** return a date number for the given date that can be used in computations.
27  * input:
28  *
29  * > y : 4 digit year
30  * > m : 2 digit month
31  * > d : 2 digit day
32  *
33  */
34 long gregorian_number(long y, long m, long d);
35 
36 /** input:
37  *
38  * > g : date number computed from gregorian_number
39  *
40  * returns:
41  *
42  * > y : 4 digit year
43  * > m : 2 digit month
44  * > d : 2 digit day
45  *
46  */
47 void date_from_gregorian_number(long g, long &y, long &m, long &d);
48 
49 /**
50  * input:
51  *
52  * > y : 4 digit year
53  * > m : 2 digit month
54  * > d : 2 digit day
55  *
56  * returns:
57  *
58  * true if the date is valid in the gregorian calendar and our conversion
59  * algorithm.
60 */
61 bool valid_gregorian_date(long y, long m, long d);
62 ///@}
63 
64 
65 /// returns one of DJF,MAM,JJA,SON based on the month passed in
66 const char *get_season_name(int month);
67 
68 /** brief
69  * A floating point time value and its corresponding year, month day, hour
70  * minute and second
71  */
72 struct time_point
73 {
74  time_point() : index(-1), time(0.0), year(0), month(1), day(1),
75  hour(0), minute(0), second(0.0)
76  {}
77 
78  /** Initialize explicitly.
79  * @param[in] i the index of the time value
80  * @param[in] t the time value
81  * @param[in] YYYY the year
82  * @param[in] MM the month
83  * @param[in] DD the day
84  * @param[in] hh the hour
85  * @param[in] mm the minute
86  * @param[in] ss the second
87  */
88  time_point(long i, double t, int YYYY=0, int MM=1, int DD=1,
89  int hh=0, int mm=0, double ss=0.0) : index(i), time(t),
90  year(YYYY), month(MM), day(DD), hour(hh), minute(mm),
91  second(ss)
92  {}
93 
94 
95  /** Initialize from a floating point time value. The calendar and units
96  * must be provided.
97  * @param[in] i the index of the time value
98  * @param[in] t the time value
99  * @param[in] units the units t is in
100  * @param[in] calendar the calendar system the units are in
101  */
102  time_point(long i, double t,
103  const std::string &units, const std::string &calendar);
104 
105  long index;
106  double time;
107  int year;
108  int month;
109  int day;
110  int hour;
111  int minute;
112  double second;
113 };
114 
115 /// An iterator over a series of time intervals
117 {
118 public:
119 
120  interval_iterator() : time(), units(), calendar(),
121  begin(), end(), valid(false)
122  {}
123 
124  virtual ~interval_iterator() {}
125 
126  /** Initialize the iterator from a metadata object following the
127  * conventions defined by the teca_cf_reader.
128  * @returns 0 if successfully initialized
129  */
130  virtual int initialize(const teca_metadata &md);
131 
132  /** Initialize the iterator from a metadata object following the
133  * conventions defined by the teca_cf_reader.
134  * @param[in] md a metadata object
135  * @param[in] first_step the first step to include in the series or 0 to use all
136  * @param[in] last_step the last step to include in the series or -1 to use all
137  * @returns 0 if successfully initialized
138  */
139  virtual int initialize(const teca_metadata &md,
140  long first_step, long last_step);
141 
142  /** Initialize the iterator.
143  * @param[in] t An array of time values
144  * @param[in] units A string units of the time values
145  * @param[in] calendar A string name of the calendar system
146  * @param[in] first_step the first step to include in the series or 0 to use all
147  * @param[in] last_step the last step to include in the series or -1 to use all
148  * @returns 0 if successfully initialized
149  */
150  virtual int initialize(const const_p_teca_variant_array &t,
151  const std::string &units, const std::string &calendar,
152  long first_step, long last_step) = 0;
153 
154  /// return true if there are more time steps in the sequence
155  virtual bool is_valid() const = 0;
156 
157  /** Get the next interval in the series.
158  * @param[out] first_step The first step in the next element of the series
159  * @param[out] last_step The last step in the next element of the series
160  * @returns 0 if successfully initialized
161  */
162  virtual int get_next_interval(time_point &first_step,
163  time_point &last_step) = 0;
164 
165  /// @returns true if there are more intervals in the series
166  operator bool() const
167  {
168  return this->is_valid();
169  }
170 
171  /// return the first time point in the series
172  const time_point &get_begin() const { return this->begin; }
173 
174  /// return the last time point in the series
175  const time_point &get_end() const { return this->end; }
176 
177 protected:
179  std::string units;
180  std::string calendar;
181  time_point begin;
182  time_point end;
183  bool valid;
184 };
185 
186 /// Enumerate ranges of time steps bracketing seasons
187 /**
188  * An iterator over seasons (DJF, MAM, JJA, SON) between 2 time_point's. A
189  * pair of time steps bracketing the current season are returned at each
190  * iteration. Only full seasonal intervals are processed. If the input data
191  * doesn't start or end on a seasonal boundary, the data from the start to the
192  * first full season, and the data from the end of the last full season to the
193  * end is skipped.
194  */
196 {
197 public:
198  season_iterator() : year(-1), month(-1) {}
199 
200  /// return true if there are more time steps in the sequence
201  bool is_valid() const override;
202 
203  /** Initialize the iterator.
204  *
205  * @param[in] t An array of time values
206  * @param[in] units A string units of the time values
207  * @param[in] calendar A string name of the calendar system
208  * @param[in] first_step the first step to include in the series or 0 to use all
209  * @param[in] last_step the last step to include in the series or -1 to use all
210  * @returns 0 if successfully initialized
211  */
213  const std::string &units, const std::string &calendar,
214  long first_step, long last_step) override;
215 
216  /** return a pair of time steps bracketing the current season.
217  * both returned time steps belong to the current season.
218  */
219  int get_next_interval(time_point &first_step,
220  time_point &last_step) override;
221 
222 private:
223  /** given a year and month, checks that the values fall on a seasonal
224  * boundary. if not, returns the year and month of the start of the next
225  * season.
226  */
227  int get_first_season(int y_in, int m_in, int &y_out, int &m_out) const;
228 
229  /** Given a year and month returns the year month and day of the end of the
230  * season. the input month need not be on a seasonal boundary.
231  */
232  int get_season_end(int y_in, int m_in,
233  int &y_out, int &m_out, int &d_out) const;
234 
235  /** Given a year and month returns the year and month of the next season.
236  * the input momnth doesn't need to be on a seasonal boundary.
237  */
238  int get_next_season(int y_in, int m_in, int &y_out, int &m_out) const;
239 
240 protected:
241  int year;
242  int month;
243 };
244 
245 /// Enumerate ranges of time steps bracketing months
246 /** An iterator over all months between 2 time_point's. A pair
247  * of time steps bracketing the current month are returned at
248  * each iteration.
249  */
251 {
252 public:
253  year_iterator() : year(-1) {}
254 
255  /// return true if there are more time steps in the sequence
256  bool is_valid() const override;
257 
258  /** Initialize the iterator.
259  *
260  * @param[in] t An array of time values
261  * @param[in] units A string units of the time values
262  * @param[in] calendar A string name of the calendar system
263  * @param[in] first_step the first step to include in the series or 0 to use all
264  * @param[in] last_step the last step to include in the series or -1 to use all
265  * @returns 0 if successfully initialized
266  */
268  const std::string &units, const std::string &calendar,
269  long first_step, long last_step) override;
270 
271  /** return a pair of time steps bracketing the current season.
272  * both returned time steps belong to the current season.
273  */
274  int get_next_interval(time_point &first_step,
275  time_point &last_step) override;
276 
277 protected:
278  int year;
279 };
280 
281 /// Enumerate ranges of time steps bracketing months
282 /** An iterator over all months between 2 time_point's. A pair
283  * of time steps bracketing the current month are returned at
284  * each iteration.
285  */
287 {
288 public:
289  month_iterator() : year(-1), month(-1) {}
290 
291  /// return true if there are more time steps in the sequence
292  bool is_valid() const override;
293 
294  /** Initialize the iterator.
295  *
296  * @param[in] t An array of time values
297  * @param[in] units A string units of the time values
298  * @param[in] calendar A string name of the calendar system
299  * @param[in] first_step the first step to include in the series or 0 to use all
300  * @param[in] last_step the last step to include in the series or -1 to use all
301  * @returns 0 if successfully initialized
302  */
304  const std::string &units, const std::string &calendar,
305  long first_step, long last_step) override;
306 
307  /** return a pair of time steps bracketing the current season.
308  * both returned time steps belong to the current season.
309  */
310  int get_next_interval(time_point &first_step,
311  time_point &last_step) override;
312 
313 protected:
314  int year;
315  int month;
316 };
317 
318 /// Enumerate ranges of time steps bracketing days
319 /** An iterator over all days between 2 time_point's. A pair
320  * of time steps bracketing the current day are returned at
321  * each iteration.
322  */
324 {
325 public:
326  day_iterator() : year(-1), month(-1), day(-1) {}
327 
328  /// return true if there are more time steps in the sequence
329  bool is_valid() const override;
330 
331  /** Initialize the iterator.
332  *
333  * @param[in] t An array of time values
334  * @param[in] units A string units of the time values
335  * @param[in] calendar A string name of the calendar system
336  * @param[in] first_step the first step to include in the series or 0 to use all
337  * @param[in] last_step the last step to include in the series or -1 to use all
338  * @returns 0 if successfully initialized
339  */
341  const std::string &units, const std::string &calendar,
342  long first_step, long last_step) override;
343 
344  /** return a pair of time steps bracketing the current season.
345  * both returned time steps belong to the current season.
346  */
347  int get_next_interval(time_point &first_step,
348  time_point &last_step) override;
349 
350 protected:
351  int year;
352  int month;
353  int day;
354 };
355 
356 
357 using p_interval_iterator = std::shared_ptr<interval_iterator>;
358 
359 /// A factory for interval_iterator
361 {
362 public:
363  /** Allocate and return an instance of the named iterator
364  * @param[in] interval Name of the desired interval iterator. One of daily,
365  * monthly, seasonal, or yearly
366  * @returns an instance of interval_iterator
367  */
368  static p_interval_iterator New(const std::string &interval);
369 
370  /// The available intervals
371  enum {invalid = 0, daily = 2, monthly = 3, seasonal = 4, yearly = 5};
372 
373  /** Allocate and return an instance of the named iterator
374  * @param[in] interval Id of the desired interval iterator. One of daily,
375  * monthly, seasonal, or yearly
376  * @returns an instance of interval_iterator
377  */
378  static p_interval_iterator New(int interval);
379 };
380 
381 }
382 
383 /// send the time_point to a stream in humnan readable form
384 std::ostream &operator<<(std::ostream &os,
385  const teca_calendar_util::time_point &tpt);
386 
387 #endif
teca_variant_array.h
teca_calendar_util::date_from_gregorian_number
void date_from_gregorian_number(long g, long &y, long &m, long &d)
teca_metadata
A generic container for meta data in the form of name=value pairs.
Definition: teca_metadata.h:18
teca_calendar_util::valid_gregorian_date
bool valid_gregorian_date(long y, long m, long d)
teca_calendar_util::season_iterator::initialize
int initialize(const const_p_teca_variant_array &t, const std::string &units, const std::string &calendar, long first_step, long last_step) override
teca_calendar_util::interval_iterator::get_end
const time_point & get_end() const
return the last time point in the series
Definition: teca_calendar_util.h:175
teca_calendar_util::time_point::time_point
time_point(long i, double t, int YYYY=0, int MM=1, int DD=1, int hh=0, int mm=0, double ss=0.0)
Definition: teca_calendar_util.h:88
teca_calendar_util::year_iterator::get_next_interval
int get_next_interval(time_point &first_step, time_point &last_step) override
teca_calendar_util::month_iterator::get_next_interval
int get_next_interval(time_point &first_step, time_point &last_step) override
teca_calendar_util::day_iterator
Enumerate ranges of time steps bracketing days.
Definition: teca_calendar_util.h:323
teca_calendar_util::interval_iterator::get_next_interval
virtual int get_next_interval(time_point &first_step, time_point &last_step)=0
teca_calendar_util::year_iterator::is_valid
bool is_valid() const override
return true if there are more time steps in the sequence
teca_calendar_util
Codes dealing with calendaring.
Definition: teca_calendar_util.h:15
teca_calendar_util::gregorian_number
long gregorian_number(long y, long m, long d)
teca_calendar_util::interval_iterator::get_begin
const time_point & get_begin() const
return the first time point in the series
Definition: teca_calendar_util.h:172
teca_calendar_util::interval_iterator
An iterator over a series of time intervals.
Definition: teca_calendar_util.h:116
teca_calendar_util::interval_iterator::is_valid
virtual bool is_valid() const =0
return true if there are more time steps in the sequence
teca_calendar_util::month_iterator
Enumerate ranges of time steps bracketing months.
Definition: teca_calendar_util.h:286
teca_calendar_util::month_iterator::initialize
int initialize(const const_p_teca_variant_array &t, const std::string &units, const std::string &calendar, long first_step, long last_step) override
const_p_teca_variant_array
std::shared_ptr< const teca_variant_array > const_p_teca_variant_array
Definition: teca_variant_array.h:22
teca_calendar_util::day_iterator::is_valid
bool is_valid() const override
return true if there are more time steps in the sequence
teca_calendar_util::season_iterator::is_valid
bool is_valid() const override
return true if there are more time steps in the sequence
teca_calendar_util::month_iterator::is_valid
bool is_valid() const override
return true if there are more time steps in the sequence
teca_calendar_util::interval_iterator_factory
A factory for interval_iterator.
Definition: teca_calendar_util.h:360
teca_calendar_util::interval_iterator::initialize
virtual int initialize(const teca_metadata &md)
teca_calendar_util::year_iterator
Enumerate ranges of time steps bracketing months.
Definition: teca_calendar_util.h:250
teca_calendar_util::day_iterator::get_next_interval
int get_next_interval(time_point &first_step, time_point &last_step) override
teca_calendar_util::time_point
Definition: teca_calendar_util.h:72
teca_calendar_util::season_iterator::get_next_interval
int get_next_interval(time_point &first_step, time_point &last_step) override
teca_calendar_util::year_iterator::initialize
int initialize(const const_p_teca_variant_array &t, const std::string &units, const std::string &calendar, long first_step, long last_step) override
teca_calendar_util::day_iterator::initialize
int initialize(const const_p_teca_variant_array &t, const std::string &units, const std::string &calendar, long first_step, long last_step) override
teca_calendar_util::interval_iterator_factory::New
static p_interval_iterator New(const std::string &interval)
operator<<
std::ostream & operator<<(std::ostream &os, const teca_calendar_util::time_point &tpt)
send the time_point to a stream in humnan readable form
teca_calendar_util::season_iterator
Enumerate ranges of time steps bracketing seasons.
Definition: teca_calendar_util.h:195
teca_calendar_util::get_season_name
const char * get_season_name(int month)
returns one of DJF,MAM,JJA,SON based on the month passed in