/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          CDateTime.h  -  description
                             -------------------
    begin                : Tue Dec 14 1999
    copyright            : (C) 1999-2005 by Alexey Parshin
    email                : alexeyp@gmail.com
 ***************************************************************************/

/***************************************************************************
   This library is free software; you can redistribute it and/or modify it 
   under the terms of the GNU Library General Public License as published by
   the Free Software Foundation; either version 2 of the License, or (at 
   your option) any later version.

   This library is distributed in the hope that it will be useful, but 
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
   General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; if not, write to the Free Software Foundation, 
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

   Please report all bugs and problems to "alexeyp@gmail.com"
 ***************************************************************************/

#ifndef __CDATETIME_H__
#define __CDATETIME_H__

#include <sptk3/sptk.h>
#include <string>

/// @addtogroup utility Utility Classes
/// @{

class CDateTime;
class CDateTimeFormat;

/// Compares CDatetime values
bool operator <  (const CDateTime &dt1, const CDateTime &dt2);

/// Compares CDatetime values
bool operator <= (const CDateTime &dt1, const CDateTime &dt2);

/// Compares CDatetime values
bool operator >  (const CDateTime &dt1, const CDateTime &dt2);

/// Compares CDatetime values
bool operator >= (const CDateTime &dt1, const CDateTime &dt2);

/// Compares CDatetime values
bool operator == (const CDateTime &dt1, const CDateTime &dt2);

/// Compares CDatetime values
bool operator != (const CDateTime &dt1, const CDateTime &dt2);

/// @brief Date and Time value.
///
/// Represents the date and time value. This value is stored as
/// a floating point number.
class SP_EXPORT CDateTime {
   friend class CDateTimeFormat;
protected:

   /// Internal decode date operation into y,m,d
   static void   decodeDate(const double dt,short& y,short& m,short& d);

   /// Internal decode time operation into h,m,s,ms
   static void   decodeTime(const double dt,short& h,short& m,short& s,short& ms);

   /// Internal encode date operation from y,m,d
   static void   encodeDate(double &dt,short y=0,short m=0,short d=0);

   /// Internal encode date operation from string
   static void   encodeDate(double &dt,const char *dat);

   /// Internal encode timee operation from h,m,s,ms
   static void   encodeTime(double &dt,short h=0,short m=0,short s=0,short ms=0);

   /// Internal encode timee operation from string
   static void   encodeTime(double &dt,const char *tim);

   /// Returns true for the leap year
   static int    isLeapYear(const short year);

protected:

   double                m_dateTime;             ///< Actual date and time value

   /// The offset from current' system time for synchronization
   /// with outside system
   static double         m_dateTimeOffset;    
   static bool           m_time24Mode;           ///< System's time mode
public:

   static char           dateFormat[32];         ///< System's date format
   static char           fullTimeFormat[32];     ///< System's time format
   static char           shortTimeFormat[32];    ///< System's time format
   static char           datePartsOrder[4];      ///< System's date parts order 
   static char           dateSeparator;          ///< System's date separator
   static char           timeSeparator;          ///< System's time separator
   static std::string    weekDayNames[7];        ///< The locale-defined weekday names
   static std::string    monthNames[12];         ///< The locale-defined weekday names
   static std::string    timeZoneName;           ///< Time zone abbbreviastion
   static int            timeZoneOffset;         ///< Time zone offset from GMT in hours

public:

   /// Constructor
   /// @param y short, year
   /// @param m short, month
   /// @param d short, day
   /// @param h short, hour
   /// @param mm short, minute
   /// @param s short, second
   CDateTime (short y,short m,short d,short h=0,short mm=0,short s=0);

   /// Constructor
   /// @param dateStr const char *, date string
   CDateTime (const char * dateStr);

   /// Copy constructor
   CDateTime (const CDateTime &dt);

   /// Constructor
   /// @param dt double, floating point date and time value
   CDateTime (const double dt=0);

   /// Conversion to double
   operator double () const;

   /// Assignment
   void operator = (const CDateTime& date);

   /// Assignment
   void operator = (const char * dat);

   /// Addition, in days
   CDateTime  operator + (int i);

   /// Substruction, in days
   CDateTime  operator - (int i);

   /// Addition, another CDateTime
   CDateTime  operator + (CDateTime& dt);

   /// Substruction, another CDateTime
   CDateTime  operator - (CDateTime& dt);

   /// Increment by days
   CDateTime& operator += (int i);

   /// Decrement by days
   CDateTime& operator -= (int i);

   /// Increment by another CDateTime
   CDateTime& operator += (CDateTime& dt);

   /// Decrement by another CDateTime
   CDateTime& operator -= (CDateTime& dt);

   /// Increment by day, prefix
   CDateTime& operator ++ ();   

   /// Increment by day, postfix
   CDateTime& operator ++ (int);

   /// Decrement by day, prefix
   CDateTime& operator -- ();     

   /// Decrement by day, postfix
   CDateTime& operator -- (int);  

   /// Compare operation
   friend bool operator <  (const CDateTime &dt1, const CDateTime &dt2);

   /// Compare operation
   friend bool operator <= (const CDateTime &dt1, const CDateTime &dt2);

   /// Compare operation
   friend bool operator >  (const CDateTime &dt1, const CDateTime &dt2);

   /// Compare operation
   friend bool operator >= (const CDateTime &dt1, const CDateTime &dt2);

   /// Compare operation
   friend bool operator == (const CDateTime &dt1, const CDateTime &dt2);

   /// Compare operation
   friend bool operator != (const CDateTime &dt1, const CDateTime &dt2);

   /// Print the date into str
   void formatDate(char *str) const;

   /// Print the date into str
   void formatTime(char *str,bool ampm=true,bool showSeconds=false) const;

   /// Set the current date and time for this program only.
   /// The system time is not affected. Useful for synchronization between
   /// different hosts' programs.
   static void Now(CDateTime dt);

   /// Reports the system date and time.
   static CDateTime System();

   /// Reports the current date and time.
   static CDateTime Now();

   /// Reports the current date.
   static CDateTime Date();           

   /// Reports the current time.
   static CDateTime Time();           

   /// Converts C time into CDateTime
   static CDateTime convertCTime(const long tt);

   /// Reports the number of days in the month in this date (1..31)
   short daysInMonth() const;         

   /// Reports the day of the week in this date (1..7)
   short dayOfWeek(void) const;       

   /// Reports the day since the beginning of the year in this date
   short dayOfYear()  const;  

   /// Reports the day of the week name in this date ('Sunday'..'Saturday')
   std::string dayOfWeekName(void) const;

   /// Reports the month name in this date ('Sunday'..'Saturday')
   std::string monthName() const;

   /// Reports the date as an integer
   unsigned date() const;

   /// Reports the day of month (1..31)
   short day() const;

   /// Reports the month number (1..12)
   short month() const;

   /// Reports the year
   short year() const;
public:

   /// Returns date as a string
   std::string dateString() const;

   /// Returns time as a string
   std::string timeString(bool showSeconds=false) const;

   /// Returns date and time as a string
   operator std::string () const { return dateString() + " " + timeString(); }
public:

   /// Decodes date into y,m,d
   void decodeDate(short *y,short *m,short *d) const;

   /// Decodes time into h,m,s,ms
   void decodeTime(short *h,short *m,short *s,short *ms) const;

   /// Returns system's time mode.
   static bool time24Mode() { return m_time24Mode; }

   /// Sets system's time mode
   static void time24Mode(bool t24mode);          
};

/// @}

#endif
