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