/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

#ifndef _QWT_DATE_H_
#define _QWT_DATE_H_

#include "qwt_global.h"
#include <qdatetime.h>

/*!
  \brief A collection of methods around date/time values

  Qt offers convenient classes for dealing with date/time values,
  but Qwt uses coordinate systems that are based on doubles.
  QwtDate offers methods to translate from QDateTime to double and v.v.

  A double is interpreted as the number of milliseconds since
  1970-01-01T00:00:00 Universal Coordinated Time - also known
  as "The Epoch". 

  While the range of the Julian day in Qt4 is limited to [0, MAX_INT], 
  Qt5 stores it as qint64 offering a huge range of valid dates. 
  As the significance of a double is below this ( assuming a 
  fraction of 52 bits ) the translation is not 
  bijective with rounding errors for dates very far from Epoch. 
  For a resolution of 1 ms those start to happen for dates above the 
  year 144683. 

  An axis for a date/time interval is expected to be aligned
  and divided in time/date units like seconds, minutes, ...
  QwtDate offers several algorithms that are needed to
  calculate these axes.

  \sa QwtDateScaleEngine, QwtDateScaleDraw, QDate, QTime
*/
class QWT_EXPORT QwtDate
{
public:
    /*! 
       How to identify the first week of year differs between
       countries. 
     */
    enum Week0Type
    {
        /*!
           According to ISO 8601 the first week of a year is defined
           as "the week with the year's first Thursday in it".

           FirstThursday corresponds to the numbering that is
           implemented in QDate::weekNumber().
        */
        FirstThursday,

        /*!
            "The week with January 1.1 in it."
           
            In the U.S. this definition is more common than
            FirstThursday.
        */
        FirstDay
    };

    /*! 
      Classification of an time interval

      Time intervals needs to be classified to decide how to
      align and divide it.
     */
    enum IntervalType
    {
        //! The interval is related to milliseconds
        Millisecond,

        //! The interval is related to seconds
        Second,

        //! The interval is related to minutes
        Minute,

        //! The interval is related to hours
        Hour,

        //! The interval is related to days
        Day,

        //! The interval is related to weeks
        Week,

        //! The interval is related to months
        Month,

        //! The interval is related to years
        Year
    };

    enum
    {
        //! The Julian day of "The Epoch"
        JulianDayForEpoch = 2440588
    };

    static QDate minDate();
    static QDate maxDate();

    static QDateTime toDateTime( double value, 
        Qt::TimeSpec = Qt::UTC );

    static double toDouble( const QDateTime & );

    static QDateTime ceil( const QDateTime &, IntervalType );
    static QDateTime floor( const QDateTime &, IntervalType );

    static QDate dateOfWeek0( int year, Week0Type );
    static int weekNumber( const QDate &, Week0Type );

    static int utcOffset( const QDateTime & );

    static QString toString( const QDateTime &, 
        const QString & format, Week0Type );
};

#endif
