source: XIOS/trunk/src/node/calendar_wrapper.cpp @ 549

Last change on this file since 549 was 549, checked in by rlacroix, 6 years ago

Revised calendar functionalities:

  • the calendar is now configured from a specific calendar child node of the context in the XML configuration file. Example: <calendar type="Gregorian" start_date="2012-03-01 15:00:00" time_origin="2012-02-29 15:00:00" timestep="1h" />
  • the calendar type should now be configured when defining the start time and/or the time origin.
  • the start time and the time origin are now optional, 0000-01-01 00:00:00 will be used by default. It is also possible to define them partially. For example, 2015 and 2014-12 are valid dates corresponding respectively to 2015-01-01 00:00:00 and 2014-12-01 00:00:00.
  • an optional duration offset can be added to the start date and time origin. For example, it's possible to define the date 2015-01-12 12:00:00 as 2015-01-11 + 36h or 2015-01-11 12:00:00 + 1d. The duration format is the same as the time step. Being that the date is optional, it is possible to only use a duration (for example + 42s is the same as 0000-01-01 00:00:00 + 42s). An error will be raised if a duration based on the time step is used before the time step was configured. For example, the following would cause an error: <calendar type="Gregorian" start_date="+ 1ts" /> but <calendar type="Gregorian" start_date="+ 1ts" timestep="0.5h" /> would not.
  • new Fortran interface to define the calendar:
    • xios_define_calendar(type[, timestep, start_date, time_origin]) will create a calendar when none had previously been defined. Only the type argument is mandatory, the rest is optional. Calendar operations on dates and durations are possible as soon as the calendar is created (either using this procedure or directly from the XML configuration file).
    • the following getter and setter procedures are available: xios_set_timestep, xios_set_start_date, xios_set_time_origin, xios_get_calendar_type, xios_get_timestep, xios_get_start_date, xios_get_time_origin.
  • new Fortran interface to interact with the calendar: xios_update_calendar, xios_get_current_date, xios_get_year_length_in_seconds, xios_get_day_length_in_seconds.
  • new Fortran interface for date conversion: xios_date_get_second_of_year, xios_date_get_day_of_year, xios_date_get_fraction_of_year, xios_date_get_second_of_day, xios_date_get_fraction_of_day.
  • two new placeholders are available to format the file name when splitting the output (split_freq_format attribute):
    • %S the number of seconds since the time origin
    • %D the integral number of days since the time origin
File size: 4.4 KB
Line 
1#include "calendar_wrapper.hpp"
2#include "type.hpp"
3#include "calendar_type.hpp"
4#include "duration.hpp"
5#include "context.hpp"
6
7namespace xios {
8
9  /// ////////////////////// Définitions ////////////////////// ///
10
11  CCalendarWrapper::CCalendarWrapper(void)
12    : CObjectTemplate<CCalendarWrapper>(), CCalendarWrapperAttributes()
13  { /* Ne rien faire de plus */ }
14
15  CCalendarWrapper::CCalendarWrapper(const StdString & id)
16    : CObjectTemplate<CCalendarWrapper>(id), CCalendarWrapperAttributes()
17  { /* Ne rien faire de plus */ }
18
19  CCalendarWrapper::~CCalendarWrapper(void)
20  {}
21
22  //----------------------------------------------------------------
23
24  StdString CCalendarWrapper::GetName(void)    { return StdString("calendar_wrapper"); }
25  StdString CCalendarWrapper::GetDefName(void) { return StdString("calendar"); }
26  ENodeType CCalendarWrapper::GetType(void)    { return eCalendarWrapper; }
27
28  //----------------------------------------------------------------
29
30  /*!
31  \brief Extract the calendar from its wrapper
32  \return the calendar
33  */
34  boost::shared_ptr<CCalendar> CCalendarWrapper::getCalendar(bool checkValid /*= false*/) const
35  {
36    if (checkValid && !this->calendar)
37      ERROR("CCalendarWrapper::getCalendar(bool checkValid = true)", << "The calendar was accessed before being created!");
38    return this->calendar;
39  }
40
41  const CDate& CCalendarWrapper::getInitDate() const
42  {
43    return getCalendar(true)->getInitDate();
44  }
45
46  const CDate& CCalendarWrapper::getTimeOrigin() const
47  {
48    return getCalendar(true)->getTimeOrigin();
49  }
50
51  //----------------------------------------------------------------
52
53  void CCalendarWrapper::setInitDate(const CDate& initDate)
54  {
55    getCalendar(true)->setInitDate(initDate);
56    start_date = initDate.toString();
57  }
58
59  void CCalendarWrapper::setTimeOrigin(const CDate& timeOrigin)
60  {
61    getCalendar(true)->setTimeOrigin(timeOrigin);
62    time_origin = timeOrigin.toString();
63  }
64
65  //----------------------------------------------------------------
66
67  /*!
68  \brief Parse the calendar node
69  \param [in] node xmld node corresponding to the calendar definition
70  */
71  void CCalendarWrapper::parse(xml::CXMLNode& node)
72  {
73    SuperClass::parse(node);
74
75    // Try to create the calendar
76    createCalendar();
77  }
78
79  /*!
80  \brief Try to create the calendar from the parsed attributes
81  */
82  void CCalendarWrapper::createCalendar(void)
83  {
84    // Create the calendar if possible
85    if (calendar)
86    {
87      ERROR("CCalendarWrapper::createCalendar(void)",
88            << "Error: the calendar can only be defined once!");
89    }
90    else if (!type.isEmpty())
91    {
92#define DECLARE_CALENDAR(MType, eType)                                     \
93      if (type.getValue() == type_attr::eType)                             \
94        calendar = boost::shared_ptr<CCalendar>(new C##MType##Calendar());
95#include "calendar_type.conf"
96#undef DECLARE_CALENDAR
97
98      if (!calendar)
99        ERROR("CCalendarWrapper::parse(xml::CXMLNode& node)",
100              << "[ type = " << type.getStringValue() << " ] "
101              << "The calendar is not properly handled!");
102
103      // Set the timestep is available
104      if (!timestep.isEmpty())
105        calendar->setTimeStep(timestep.getValue());
106
107      // Parse and set the start date if available
108      if (!start_date.isEmpty())
109        calendar->setInitDate(CDate::FromString(start_date.getValue(), *calendar));
110
111      // Parse and set the time origin if available
112      if (!time_origin.isEmpty())
113        calendar->setTimeOrigin(CDate::FromString(time_origin.getValue(), *calendar));
114
115      // Notify the context about the calendar
116      CContext* context = CContext::getCurrent();
117      if (!context)
118        ERROR("CCalendarWrapper::createCalendar(void)", << "Impossible to set the calendar: no current context available.");
119      context->setCalendar(calendar);
120    }
121    else if (!start_date.isEmpty() || !time_origin.isEmpty())
122    {
123      ERROR("CCalendarWrapper::parse(xml::CXMLNode& node)",
124            << "The calendar type must be set before defining the start date or the time origin!");
125    }
126  }
127
128  /*!
129  \brief Try to update the timestep of the calendar with the corresponding attribute
130  */
131  void CCalendarWrapper::updateTimestep(void)
132  {
133    if (timestep.isEmpty())
134    {
135      ERROR("CCalendarWrapper::updateTimestep(void)",
136            << "Error: the timestep needs to be defined!");
137    }
138    else if (calendar)
139      calendar->setTimeStep(timestep.getValue());
140  }
141}
Note: See TracBrowser for help on using the repository browser.