Index: XIOS/trunk/src/calendar_util.cpp
===================================================================
--- XIOS/trunk/src/calendar_util.cpp	(revision 642)
+++ XIOS/trunk/src/calendar_util.cpp	(revision 643)
@@ -211,4 +211,40 @@
     ///----------------------------------------------------------------
 
+    bool DurationFakeLessComparator::operator()(const CDuration& dur1, const CDuration& dur2) const
+    {
+      if (dur1.year < dur2.year)
+        return true;
+      else if (dur1.year == dur2.year)
+      {
+        if (dur1.month < dur2.month)
+          return true;
+        else if (dur1.month == dur2.month)
+        {
+          if (dur1.day < dur2.day)
+            return true;
+          else if (dur1.day == dur2.day)
+          {
+            if (dur1.hour < dur2.hour)
+              return true;
+            else if (dur1.hour == dur2.hour)
+            {
+              if (dur1.minute < dur2.minute)
+                return true;
+              else if (dur1.minute == dur2.minute)
+              {
+                if (dur1.second < dur2.second)
+                  return true;
+                else if (dur1.second == dur2.second)
+                  return (dur1.timestep < dur2.timestep);
+              }
+            }
+          }
+        }
+      }
+      return false;
+    }
+
+    ///----------------------------------------------------------------
+
 } // namespace xios
 
Index: XIOS/trunk/src/calendar_util.hpp
===================================================================
--- XIOS/trunk/src/calendar_util.hpp	(revision 642)
+++ XIOS/trunk/src/calendar_util.hpp	(revision 643)
@@ -36,4 +36,8 @@
       ///---------------------------------------------------------------
 
+      //!< Provides a fake "less" comparator for durations that can be used as a comparator for maps
+      struct DurationFakeLessComparator {
+        bool operator()(const CDuration& dur1, const CDuration& dur2) const;
+      };
 } // namespace xios
 
Index: XIOS/trunk/src/filter/binary_arithmetic_filter.cpp
===================================================================
--- XIOS/trunk/src/filter/binary_arithmetic_filter.cpp	(revision 642)
+++ XIOS/trunk/src/filter/binary_arithmetic_filter.cpp	(revision 643)
@@ -12,4 +12,5 @@
   {
     CDataPacketPtr packet(new CDataPacket);
+    packet->date = data[0]->date;
     packet->timestamp = data[0]->timestamp;
     packet->status = data[0]->status;
@@ -30,4 +31,5 @@
   {
     CDataPacketPtr packet(new CDataPacket);
+    packet->date = data[0]->date;
     packet->timestamp = data[0]->timestamp;
     packet->status = data[0]->status;
@@ -47,4 +49,5 @@
   {
     CDataPacketPtr packet(new CDataPacket);
+    packet->date = data[0]->date;
     packet->timestamp = data[0]->timestamp;
 
Index: XIOS/trunk/src/filter/data_packet.hpp
===================================================================
--- XIOS/trunk/src/filter/data_packet.hpp	(revision 642)
+++ XIOS/trunk/src/filter/data_packet.hpp	(revision 643)
@@ -5,5 +5,5 @@
 
 #include "array_new.hpp"
-#include "duration.hpp"
+#include "date.hpp"
 
 namespace xios
@@ -23,4 +23,5 @@
 
     CArray<double, 1> data; //!< Array containing the data
+    CDate date;             //!< Date associated to the data
     Time timestamp;         //!< Timestamp of the data
     StatusCode status;      //!< Status of the packet
@@ -35,4 +36,5 @@
       p->data.resize(data.shape());
       p->data = data;
+      p->date = date;
       p->timestamp = timestamp;
       p->status = status;
Index: XIOS/trunk/src/filter/source_filter.cpp
===================================================================
--- XIOS/trunk/src/filter/source_filter.cpp	(revision 642)
+++ XIOS/trunk/src/filter/source_filter.cpp	(revision 643)
@@ -14,8 +14,9 @@
 
   template <int N>
-  void CSourceFilter::streamData(Time timestamp, const CArray<double, N>& data)
+  void CSourceFilter::streamData(CDate date, const CArray<double, N>& data)
   {
     CDataPacketPtr packet(new CDataPacket);
-    packet->timestamp = timestamp;
+    packet->date = date;
+    packet->timestamp = date;
     packet->status = CDataPacket::NO_ERROR;
 
@@ -26,16 +27,17 @@
   }
 
-  template void CSourceFilter::streamData<1>(Time timestamp, const CArray<double, 1>& data);
-  template void CSourceFilter::streamData<2>(Time timestamp, const CArray<double, 2>& data);
-  template void CSourceFilter::streamData<3>(Time timestamp, const CArray<double, 3>& data);
+  template void CSourceFilter::streamData<1>(CDate date, const CArray<double, 1>& data);
+  template void CSourceFilter::streamData<2>(CDate date, const CArray<double, 2>& data);
+  template void CSourceFilter::streamData<3>(CDate date, const CArray<double, 3>& data);
 
-  void CSourceFilter::streamDataFromServer(Time timestamp, const std::map<int, CArray<double, 1> >& data)
+  void CSourceFilter::streamDataFromServer(CDate date, const std::map<int, CArray<double, 1> >& data)
   {
     CDataPacketPtr packet(new CDataPacket);
-    packet->timestamp = timestamp;
+    packet->date = date;
+    packet->timestamp = date;
     packet->status = CDataPacket::NO_ERROR;
 
     if (data.size() != grid->storeIndex_toSrv.size())
-      ERROR("CSourceFilter::streamDataFromServer(Time timestamp, const std::map<int, CArray<double, 1> >& data)",
+      ERROR("CSourceFilter::streamDataFromServer(CDate date, const std::map<int, CArray<double, 1> >& data)",
             << "Incoherent data received from servers,"
             << " expected " << grid->storeIndex_toSrv.size() << " chunks but " << data.size() << " were given.");
@@ -54,8 +56,9 @@
   }
 
-  void CSourceFilter::signalEndOfStream(Time timestamp)
+  void CSourceFilter::signalEndOfStream(CDate date)
   {
     CDataPacketPtr packet(new CDataPacket);
-    packet->timestamp = timestamp;
+    packet->date = date;
+    packet->timestamp = date;
     packet->status = CDataPacket::END_OF_STREAM;
     deliverOuput(packet);
Index: XIOS/trunk/src/filter/source_filter.hpp
===================================================================
--- XIOS/trunk/src/filter/source_filter.hpp	(revision 642)
+++ XIOS/trunk/src/filter/source_filter.hpp	(revision 643)
@@ -28,9 +28,9 @@
        * immediately after this method returns.
        *
-       * \param timestamp the timestamp of the data
+       * \param date the date associated to the data
        * \param data an array containing the data
        */
       template <int N>
-      void streamData(Time timestamp, const CArray<double, N>& data);
+      void streamData(CDate date, const CArray<double, N>& data);
 
       /*!
@@ -39,15 +39,15 @@
        * immediately after this method returns.
        *
-       * \param timestamp the timestamp of the data
+       * \param date the date associated to the data
        * \param data an array containing the data
        */
-      void streamDataFromServer(Time timestamp, const std::map<int, CArray<double, 1> >& data);
+      void streamDataFromServer(CDate date, const std::map<int, CArray<double, 1> >& data);
 
       /*!
        * Signals the filter graph that the end of stream was reached.
        *
-       * \param timestamp the timestamp at which the end of stream occurred
+       * \param date the date at which the end of stream occurred
        */
-      void signalEndOfStream(Time timestamp);
+      void signalEndOfStream(CDate date);
 
     private:
Index: XIOS/trunk/src/filter/temporal_filter.cpp
===================================================================
--- XIOS/trunk/src/filter/temporal_filter.cpp	(revision 643)
+++ XIOS/trunk/src/filter/temporal_filter.cpp	(revision 643)
@@ -0,0 +1,75 @@
+#include "temporal_filter.hpp"
+#include "functor_type.hpp"
+#include "calendar_util.hpp"
+
+namespace xios
+{
+  CTemporalFilter::CTemporalFilter(CGarbageCollector& gc, const std::string& opId,
+                                   const CDate& initDate, const CDuration samplingFreq, const CDuration samplingOffset, const CDuration opFreq,
+                                   bool ignoreMissingValue /*= false*/, double missingValue /*= 0.0*/)
+    : CFilter(gc, 1, this)
+    , samplingFreq(samplingFreq)
+    , opFreq(opFreq)
+    , nextSamplingDate(initDate + samplingOffset + initDate.getRelCalendar().getTimeStep())
+    , nextOperationDate(initDate + opFreq)
+    , isFirstOperation(true)
+  {
+#define DECLARE_FUNCTOR(MType, mtype) \
+    if (opId.compare(#mtype) == 0) \
+    { \
+      if (ignoreMissingValue) \
+      { \
+        functor.reset(new func::C##MType(tmpData, missingValue)); \
+      } \
+      else \
+      { \
+        functor.reset(new func::C##MType(tmpData)); \
+      } \
+    }
+
+#include "functor_type.conf"
+
+    if (!functor)
+      ERROR("CTemporalFilter::CTemporalFilter(CGarbageCollector& gc, const std::string& opId, ...)",
+            << "\"" << opId << "\" is not a valid operation.");
+
+    isOnceOperation = (functor->timeType() == func::CFunctor::once);
+  }
+
+  CDataPacketPtr CTemporalFilter::apply(std::vector<CDataPacketPtr> data)
+  {
+    CDataPacketPtr packet;
+
+    if (data[0]->status != CDataPacket::END_OF_STREAM)
+    {
+      const bool usePacket = isOnceOperation ? isFirstOperation : (data[0]->date >= nextSamplingDate);
+      if (usePacket)
+      {
+        if (!tmpData.numElements())
+          tmpData.resize(data[0]->data.numElements());
+
+        (*functor)(data[0]->data);
+
+        nextSamplingDate = nextSamplingDate + samplingFreq;
+      }
+
+      const bool outputResult = isOnceOperation ? isFirstOperation : (data[0]->date + samplingFreq > nextOperationDate);
+      if (outputResult)
+      {
+        functor->final();
+
+        packet = CDataPacketPtr(new CDataPacket);
+        packet->date = data[0]->date;
+        packet->timestamp = data[0]->timestamp;
+        packet->status = data[0]->status;
+        packet->data.resize(tmpData.numElements());
+        packet->data = tmpData;
+
+        isFirstOperation = false;
+        nextOperationDate = nextOperationDate + opFreq;
+      }
+    }
+
+    return packet;
+  }
+} // namespace xios
Index: XIOS/trunk/src/filter/temporal_filter.hpp
===================================================================
--- XIOS/trunk/src/filter/temporal_filter.hpp	(revision 643)
+++ XIOS/trunk/src/filter/temporal_filter.hpp	(revision 643)
@@ -0,0 +1,54 @@
+#ifndef __XIOS_CTemporalFilter__
+#define __XIOS_CTemporalFilter__
+
+#include "filter.hpp"
+#include <boost/smart_ptr/scoped_ptr.hpp>
+#include "functor.hpp"
+#include "array_new.hpp"
+
+namespace xios
+{
+  /*!
+   * A generic temporal filter with one input slot wrapping any type of temporal operation.
+   */
+  class CTemporalFilter : public CFilter, public IFilterEngine
+  {
+    public:
+      /*!
+       * Constructs a temporal filter wrapping the specified temporal operation.
+       *
+       * \param gc the associated garbage collector
+       * \param opId the string identifying the temporal operation
+       * \param initDate the origin of time
+       * \param samplingFreq the sampling frequency, i.e. the frequency at which the input data will be used
+       * \param samplingOffset the sampling offset, i.e. the offset after which the input data will be used
+       * \param opFreq the operation frequency, i.e. the frequency at which the output data will be computed
+       * \param ignoreMissingValue true if and only if the missing value must be ignored
+                                   when doing the operation
+       * \param missingValue the missing value
+       */
+      CTemporalFilter(CGarbageCollector& gc, const std::string& opId,
+                      const CDate& initDate, const CDuration samplingFreq, const CDuration samplingOffset, const CDuration opFreq,
+                      bool ignoreMissingValue = false, double missingValue = 0.0);
+
+      /*!
+       * Applies the temporal operation to the input data and returns the result when it is ready.
+       *
+       * \param data a vector of packets corresponding to each slot (one in this case)
+       * \return the result of the temporal operation or null if it is not ready yet
+       */
+      CDataPacketPtr virtual apply(std::vector<CDataPacketPtr> data);
+
+    private:
+      boost::scoped_ptr<func::CFunctor> functor; //!< The functor corresponding to the temporal operation
+      CArray<double, 1> tmpData; //!< The array of data used for temporary storage
+      const CDuration samplingFreq; //!< The sampling frequency, i.e. the frequency at which the input data will be used
+      const CDuration opFreq; //!< The operation frequency, i.e. the frequency at which the output data will be computed
+      CDate nextSamplingDate; //!< The date of the next sampling
+      CDate nextOperationDate; //!< The date of the next operation
+      bool isFirstOperation; //!< True before the first operation was been computed
+      bool isOnceOperation; //!< True if the operation should be computed just once
+  }; // class CTemporalFilter
+} // namespace xios
+
+#endif //__XIOS_CTemporalFilter__
Index: XIOS/trunk/src/filter/unary_arithmetic_filter.cpp
===================================================================
--- XIOS/trunk/src/filter/unary_arithmetic_filter.cpp	(revision 642)
+++ XIOS/trunk/src/filter/unary_arithmetic_filter.cpp	(revision 643)
@@ -11,4 +11,5 @@
   {
     CDataPacketPtr packet(new CDataPacket);
+    packet->date = data[0]->date;
     packet->timestamp = data[0]->timestamp;
     packet->status = data[0]->status;
Index: XIOS/trunk/src/node/field.cpp
===================================================================
--- XIOS/trunk/src/node/field.cpp	(revision 642)
+++ XIOS/trunk/src/node/field.cpp	(revision 643)
@@ -21,4 +21,5 @@
 #include "filter_expr_node.hpp"
 #include "lex_parser.hpp"
+#include "temporal_filter.hpp"
 
 namespace xios{
@@ -810,5 +811,5 @@
        {
          fileWriterFilter = boost::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this));
-         instantDataFilter->connectOutput(fileWriterFilter, 0);
+         getTemporalDataFilter(gc, file->output_freq)->connectOutput(fileWriterFilter, 0);
        }
      }
@@ -834,4 +835,42 @@
 
      return clientSourceFilter;
+   }
+
+   /*!
+    * Returns the temporal filter corresponding to the field's temporal operation
+    * for the specified operation frequency. The filter is created if it does not
+    * exist, otherwise it is reused.
+    *
+    * \param gc the garbage collector to use
+    * \param outFreq the operation frequency, i.e. the frequency at which the output data will be computed
+    * \return the output pin corresponding to the requested temporal filter
+    */
+   boost::shared_ptr<COutputPin> CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)
+   {
+     std::map<CDuration, boost::shared_ptr<COutputPin> >::iterator it = temporalDataFilters.find(outFreq);
+
+     if (it == temporalDataFilters.end())
+     {
+       if (operation.isEmpty())
+         ERROR("void CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)",
+               << "An operation must be defined for field \"" << getId() << "\".");
+
+       if (freq_op.isEmpty())
+         freq_op.setValue(TimeStep);
+       if (freq_offset.isEmpty())
+         freq_offset.setValue(NoneDu);
+
+       const bool ignoreMissingValue = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true);
+
+       boost::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation,
+                                                                             CContext::getCurrent()->getCalendar()->getInitDate(),
+                                                                             freq_op, freq_offset, outFreq,
+                                                                             ignoreMissingValue, ignoreMissingValue ? default_value : 0.0));
+       instantDataFilter->connectOutput(temporalFilter, 0);
+
+       it = temporalDataFilters.insert(std::make_pair(outFreq, temporalFilter)).first;
+     }
+
+     return it->second;
    }
 
Index: XIOS/trunk/src/node/field.hpp
===================================================================
--- XIOS/trunk/src/node/field.hpp	(revision 642)
+++ XIOS/trunk/src/node/field.hpp	(revision 643)
@@ -134,4 +134,5 @@
          void buildFilterGraph(CGarbageCollector& gc, bool enableOutput);
          boost::shared_ptr<COutputPin> getSelfReference(CGarbageCollector& gc);
+         boost::shared_ptr<COutputPin> getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq);
 
 //         virtual void fromBinary(StdIStream & is);
@@ -246,4 +247,6 @@
          //! The output pin of the filter providing the instant data for the field
          boost::shared_ptr<COutputPin> instantDataFilter;
+         //! The output pin of the filters providing the result of the field's temporal operation
+         std::map<CDuration, boost::shared_ptr<COutputPin>, DurationFakeLessComparator> temporalDataFilters;
          //! The source filter for data provided by the client
          boost::shared_ptr<CSourceFilter> clientSourceFilter;
Index: XIOS/trunk/src/parse_expr/filter_expr_node.cpp
===================================================================
--- XIOS/trunk/src/parse_expr/filter_expr_node.cpp	(revision 642)
+++ XIOS/trunk/src/parse_expr/filter_expr_node.cpp	(revision 643)
@@ -32,4 +32,23 @@
 
     return outputPin;
+  }
+
+  CFilterTemporalFieldExprNode::CFilterTemporalFieldExprNode(const std::string& fieldId)
+    : fieldId(fieldId)
+  { /* Nothing to do */ }
+
+  boost::shared_ptr<COutputPin> CFilterTemporalFieldExprNode::reduce(CGarbageCollector& gc, CField& thisField) const
+  {
+    if (!CField::has(fieldId))
+      ERROR("boost::shared_ptr<COutputPin> CFilterTemporalFieldExprNode::reduce(CGarbageCollector& gc, CField& thisField) const",
+            << "The field " << fieldId << " does not exist.");
+
+    CField* field = CField::get(fieldId);
+    if (field == &thisField)
+      ERROR("boost::shared_ptr<COutputPin> CFilterFieldExprNode::reduce(CGarbageCollector& gc, CField& thisField) const",
+            << "The field " << fieldId << " has an invalid reference to itself.");
+
+    field->buildFilterGraph(gc, false);
+    return field->getTemporalDataFilter(gc, thisField.freq_op.isEmpty() ? TimeStep : thisField.freq_op);
   }
 
Index: XIOS/trunk/src/parse_expr/filter_expr_node.hpp
===================================================================
--- XIOS/trunk/src/parse_expr/filter_expr_node.hpp	(revision 642)
+++ XIOS/trunk/src/parse_expr/filter_expr_node.hpp	(revision 643)
@@ -42,4 +42,25 @@
        */
       CFilterFieldExprNode(const std::string& fieldId);
+
+      virtual boost::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField) const;
+
+    private:
+      std::string fieldId; //!< The identifier of the field
+  };
+
+  /*!
+   * Expression node corresponding to a field for which the result of
+   * the temporal operation is requested instead of the instant value.
+   */
+  class CFilterTemporalFieldExprNode : public IFilterExprNode
+  {
+    public:
+      /*!
+       * Constructs an expression node corresponding
+       * to the field whose id is provided.
+       *
+       * \param fieldId the identifier of the field
+       */
+      CFilterTemporalFieldExprNode(const std::string& fieldId);
 
       virtual boost::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField) const;
Index: XIOS/trunk/src/parse_expr/yacc_parser.cpp
===================================================================
--- XIOS/trunk/src/parse_expr/yacc_parser.cpp	(revision 642)
+++ XIOS/trunk/src/parse_expr/yacc_parser.cpp	(revision 643)
@@ -1373,5 +1373,5 @@
   case 15:
 #line 78 "yacc_parser.yacc" /* yacc.c:1646  */
-    { /* TODO: Use temporal operation */ (yyval.filterNode) = new CFilterFieldExprNode(*(yyvsp[0].str)); delete (yyvsp[0].str); }
+    { (yyval.filterNode) = new CFilterTemporalFieldExprNode(*(yyvsp[0].str)); delete (yyvsp[0].str); }
 #line 1377 "yacc_parser.cpp" /* yacc.c:1646  */
     break;
Index: XIOS/trunk/src/parse_expr/yacc_parser.yacc
===================================================================
--- XIOS/trunk/src/parse_expr/yacc_parser.yacc	(revision 642)
+++ XIOS/trunk/src/parse_expr/yacc_parser.yacc	(revision 643)
@@ -76,5 +76,5 @@
 Field_expr:
             ID      { $$ = new CFilterFieldExprNode(*$1); delete $1; }
-          | AVERAGE { /* TODO: Use temporal operation */ $$ = new CFilterFieldExprNode(*$1); delete $1; }
+          | AVERAGE { $$ = new CFilterTemporalFieldExprNode(*$1); delete $1; }
           | Field_expr PLUS Field_expr   { $$ = new CFilterFieldFieldOpExprNode($1, "add", $3); }
           | Field_expr MINUS Field_expr  { $$ = new CFilterFieldFieldOpExprNode($1, "minus", $3); }
