source: XIOS/trunk/src/date/user_defined.hpp @ 550

Last change on this file since 550 was 550, checked in by rlacroix, 9 years ago

Add a new user defined calendar type.

A new calendar type "user_defined" is now available. This allows the users to create a custom calendar that we can configured to be suitable for planets other than the Earth.

An user defined calendar is always defined by two mandatory attributes:

  • day_length: the duration of a day, in seconds
  • and either:
    • month_length: an array containing the duration of each month, in days (the number of elements in the array is the number of months in a year)
    • or year_length: the duration of a year, in seconds (in that case, the calendar does not have months).

If the calendar has months (i.e. month_length attribute is set) and only in that case, it is possible to define leap years in order to compensate for the duration of an astronomical year not being a multiple of the day length. The leap years are defined by two mandatory attributes:

  • leap_year_month: the month to which the extra day will be added in case of leap year, expressed as an integer number in the range [1, numberOfMonths]
  • and leap_year_drift: the fraction of a day representing the yearly drift between the calendar year and the astronomical year, expressed as a real number in the range [0, 1).

Optionally, one can define the leap_year_drift_offset attribute to set the original drift at the beginning of the time origin's year, again expressed as a real number in the range [0, 1). If leap_year_drift_offset + leap_year_drift is greater or equal to 1, then the first year will be a leap year.

For example, the following configuration creates a Gregorian-like calendar:

<calendar type="user_defined" start_date="2012-03-01 15:00:00" time_origin="2012-02-28 15:00:00 + 1d" day_length="86400" month_lengths="(1, 12) [31 28 31 30 31 30 31 31 30 31 30 31]" leap_year_month="2" leap_year_drift="0.25" leap_year_drift_offset="0.75" />

Note that dates attributes must be written differently in the configuration file when using an user defined calendar without months:

  • if the year length is greater than the day length, the input format is year-day hh:min:sec instead of year-month-day hh:min:sec
  • if the day length is greater or equal to the year length, the input format is year hh:min:sec.

In all cases, it is still possible to use the date + duration notation to build a date (with both the date and duration parts being optional).

The Fortran interface has been updated accordingly so that xios_define_calendar can accept the new attributes necessary to define custom calendars.

File size: 2.8 KB
Line 
1#ifndef __XMLIO_CUserDefinedCalendar__
2#define __XMLIO_CUserDefinedCalendar__
3
4/// xios headers ///
5#include "xmlioserver_spl.hpp"
6#include "calendar.hpp"
7#include "array_new.hpp"
8
9namespace xios
10{
11  /// ////////////////////// Déclarations ////////////////////// ///
12  /*! A custom calendar that we can configured to be suitable for planets other than the Earth. */
13  class CUserDefinedCalendar : public CCalendar
14  {
15    private:
16      /// Typedef ///
17      typedef CCalendar SuperClass;
18
19    public:
20      /// Constructor ///
21      CUserDefinedCalendar(int dayLength, const CArray<int,1>& monthLengths);
22      CUserDefinedCalendar(int dayLength, int yearLength);
23
24      /// Destructor ///
25      virtual ~CUserDefinedCalendar(void);
26
27      /// Setters ///
28      /*! Configure the leap year information. */
29      void configureLeapYear(int leapYearMonth, double leapYearDrift, double leapYearDriftOffset = 0.0);
30
31      /// Getters ///
32      virtual StdString getType(void) const;
33
34      /*! Returns the duration of the date's month in days. */
35      virtual int getMonthLength(const CDate& date) const;
36      /*! Returns the duration of the date's year in seconds. */
37      virtual int getYearTotalLength(const CDate& date) const;
38      /*! Returns the duration of a day in hours. Note that this value is
39          not necessarily exact since it can be rounded but it is always
40          the smallest integer number of hours that can hold a day. */
41      virtual int getDayLength(void) const;
42      /*! Returns the duration of a year in months. */
43      virtual int getYearLength(void) const;
44      /*! Returns the day length expressed in seconds. */
45      virtual int getDayLengthInSeconds(void) const;
46      /*! Test if the calendar can have leap year. */
47      virtual bool hasLeapYear() const;
48
49      /*! Simplify a duration based on the calendar information. */
50      virtual CDuration& resolve(CDuration& dur, bool noNegativeTime = false) const;
51
52      /*! Parse a date using the calendar's parser. */
53      virtual void parseDate(StdIStream& in, CDate& date) const;
54
55      /*! Test if a date is valid with regard to the current calendar. */
56      virtual bool checkDate(CDate& date) const;
57
58    private:
59      int dayLength; //!< length of a day in seconds
60      CArray<int,1> monthLengths; //!< length of each months in days
61      int yearLength; //!< length of a year in seconds
62
63      int leapYearMonth; //!< month to which an extra day should be added in case of a leap year
64      double leapYearDrift; //!< yearly drift (fraction of a day, must be in range [0, 1))
65      double leapYearDriftOffset; //!< initial drift (fraction of a day, must be in range [0, 1))
66
67      /*! Test if the specified year is a leap year. */
68      bool isLeapYear(int year) const;
69  }; // class CUserDefinedCalendar
70
71} // namespace xmlioserver
72
73#endif // __XMLIO_CUserDefinedCalendar__
Note: See TracBrowser for help on using the repository browser.