/***************************************************************************
                          hbcidate.h  -  description
                             -------------------
    begin                : Fri Aug 3 2001
    copyright            : (C) 2001 by fabian kaiser
    email                : fabian.kaiser@gmx.de

 ***************************************************************************
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Lesser General Public            *
 *   License as published by the Free Software Foundation; either          *
 *   version 2.1 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     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser 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                                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef HBCIDATE_H
#define HBCIDATE_H

/** @file date.h
 *
 * @short HBCI::Date, HBCI::Time, and their C wrappers @ref HBCI_Date,
 * @ref HBCI_Time. */

#ifdef __cplusplus
#include <string>
#endif /* __cplusplus */

#ifdef TM_IN_SYS_TIME
#  include <sys/time.h>
#else
#  include <time.h>
#endif
#include <openhbci/dllimport.h>

#ifdef __cplusplus
using namespace std;

namespace HBCI {
class Time;

/**
  * Represents a date in Openhbci.
  * @short Represents a date in Openhbci.
  * @author fabian kaiser
  */
class DLLIMPORT Date {
public:
    /** Create a Data.
     * @param day Day of the month, in the range 1 to 31.
     * @param month Month of the year, in the range of 1 (January)
     * to 12 (December).
     * @param year Absolute year, i.e. the number of years since year zero.
     */
    Date(int day, int month, int year);
    /** Creates a blank date; day, month, and year are set to zero. */
    Date();
    /**
     * creates a date from a string containing a HBCI conform date
     * @author Martin Preuss<openhbci@aquamaniac.de>
     *
     * @param str The string containing the HBCI conform date
     * (YYYYMMDD or YYMMDD or MMDD, depending on the argument 
     * yearsize). Note: The format with two-digit year is
     * obviously broken, but SWIFT MT940 still has it, so we need
     * to support it. Note further that Swift MT940-Specs DO NOT
     * contain information on how those two digits are to be
     * interpreted, which is a bad idea and will screw up this
     * spec at the next turn of a century. In the meantime, we
     * arbitrarily decided to interpret a two-digit year YY as
     * number of years from year 2000 if YY <= 80, and as number
     * of years from year 1900 if YY > 80.
     *
     * @param yearsize The size of the year in the string (if zero
     * then the year will not be read instead it will be set from
     * the current date); default is 4
     */
    Date(const string &str, int yearsize=4);
    /**
     * Create a Date when given a struct tm (see ctime(3)).
     */
    Date(const struct tm *tm);

    /**
     * Checks the date, and tells whether the date is valid.
     *
     * Please note: At some places in %HBCI, even the Feb 31 is
     * valid. That represents the date of actions that occur "on the
     * last day of each month". Therefore those dates are seen as
     * valid in this method.
     *
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @return true if the date is valid */
    bool isValid() const;

    /** Returns a hbci-conform string representation of given date
        (YYYYMMDD) */
    string toString() const;

    /**
     * Returns the stored day of the month, in the range 1 to 31.
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @return day (1-31);
     */
    int day() const { return _day;};

    /**
     * Returns the stored month of the year, in the range of 1 (January)
     * to 12 (December).
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @return month (1-12);
     */
    int month() const {return _month;};

    /**
     * Returns the stored year, which is the absolute number of
     * years from year zero.
     * @author Martin Preuss<openhbci@aquamaniac.de>
     * @return The absolute year in the range of 0-2100.
     */
    int year() const { return _year;};

    /**
     * Returns this date as a struct tm (see ctime(3)), but only the
     * fields tm_mday, tm_mon, and tm_year are used. All other fields
     * are still zero.
     */
    struct tm to_tm() const;

    /**
     * Returns this date as a time_t value (see time(2)), but only the
     * fields tm_mday, tm_mon, and tm_year are used. 
     */
    time_t to_time_t() const;

    /**
     * Compares the date of this object with the one given as argument.
     *
     * (This method is used by the operators.)
     *
     * @return 0 if both dates are equal; -1 if this object's date
     * occurs before the argument's date; 1 if this object's date
     * occurs after the argument's date.
     *
     * @author Martin Preuss<openhbci@aquamaniac.de>
     */
    int compare(const Date &d) const;

    /**
     * Compares Date and Time with another given Date and Time.
     *
     * Argument t1 and this object are the one point in time, and
     * arguments Date d2 and Time t2 are the other point in time.
     *
     * @return 0 if both points in time are equal; -1 if this object's
     * date and Time t1 occurs before the other point in time; 1 if
     * this object's date and Time t1 occurs after the Date d2 and
     * Time t2.
     *
     * @author Christian Stimming <stimming@tuhh.de>
     */
    int compareTime(const Time& t1, const Date& d2, const Time& t2) const;

    /**
     * sets the date
     */
    /* void setDate(int day, int month, int year); */
    /* -- uh, this seems to have disappeared! cstim, 2002/05/29 */

private:
    int _day;
    int _month;
    int _year;
};


/** Returns true if Date d1 is lesser than (occurs before) Date d2. */
inline bool operator<(const Date &d1, const Date &d2) {
    return d1.compare(d2)<0;
}


/** Returns true if Date d1 is greater than (occurs after) Date d2. */
inline bool operator>(const Date &d1, const Date &d2) {
    return d1.compare(d2)>0;
}


/** Returns true if Date d1 is equal to (is the same day as) Date d2. */
inline bool operator==(const Date &d1, const Date &d2) {
    return d1.compare(d2)==0;
}

} /* namespace HBCI */
typedef struct HBCI::Date HBCI_Date;

#else /* __cplusplus */
typedef struct Date HBCI_Date;
#endif /* __cplusplus */

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
    /** @name HBCI_Date */
    /*@{*/
    extern HBCI_Date * HBCI_Date_new(const struct tm *tm);
    extern HBCI_Date * HBCI_Date_new_blank();
    extern HBCI_Date *HBCI_Date_new_string(const char *s, int yearsize);
    extern int HBCI_Date_isValid(const HBCI_Date *h);
    extern void HBCI_Date_delete(HBCI_Date *d);
    extern struct tm HBCI_Date_to_tm(const HBCI_Date *d);
    extern time_t HBCI_Date_to_time_t(const HBCI_Date *d);
    extern int HBCI_Date_compare(const HBCI_Date *d1, const HBCI_Date *d2);
    /*@}*/
#ifdef __cplusplus
}
#endif /* __cplusplus */
    


#ifdef __cplusplus

namespace HBCI {

/**
 * @short Represents the time of day in HBCI.
  *@author fabian kaiser
  */
class DLLIMPORT Time {
  public:
    Time(int hour, int min, int sec);
    Time(const string &hbciTimeFormat);
    Time(const struct tm *tm);
    Time();
    
    /** Returns a hbci-conform string representation of given time
        (HHMMSS) */
    string toString() const;
    /** Returns the hour, in the range 0..23. */
    int hour() const { return _hour;};
    /** Returns the minutes, in the range 0..59. */
    int minute() const { return _min;};
    /** Returns the seconds, in the range 0..59. */
    int second() const { return _sec;};

    /**
     * Compares the time of this object with the one given as argument.
     *
     * @return 0 if both times are equal; -1 if this object's time
     * occurs before the argument's time; 1 if this object's time
     * occurs after the argument's time.
     *
     * @author Christian Stimming <stimming@tuhh.de>
     */
    int compare(const Time &t) const;

    /**
     * Returns this time as a struct tm (see ctime(3)), but only the
     * fields tm_hour, tm_min, and tm_sec are used. All other fields
     * are still zero.
     */
    struct tm to_tm() const;

private:
	int _hour;
	int _min;
	int _sec;
};


/** Returns true if time t1 is lesser than (occurs before) time t2. */
inline bool operator<(const Time &t1, const Time &t2) {
    return t1.compare(t2)<0;
}


/** Returns true if time t1 is greater than (occurs after) time t2. */
inline bool operator>(const Time &t1, const Time &t2) {
    return t1.compare(t2)>0;
}


/** Returns true if time t1 is equal to time t2. */
inline bool operator==(const Time &t1, const Time &t2) {
    return t1.compare(t2)==0;
}


} /* namespace HBCI */
typedef struct HBCI::Time HBCI_Time;

#else /* __cplusplus */
typedef struct HBCI_Time HBCI_Time;
#endif /* __cplusplus */


#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
    /** @name HBCI_Time */
    /*@{*/
    extern HBCI_Time * HBCI_Time_new(const struct tm *tm);
    extern void HBCI_Time_delete(HBCI_Time *d);
    extern struct tm HBCI_Time_to_tm(const HBCI_Time *d);
    extern struct tm HBCI_DateTime_to_tm(const HBCI_Date *d,
					const HBCI_Time *t);
    /*@}*/

    /** @name HBCI_Date and HBCI_Time */
    /*@{*/
    extern time_t HBCI_DateTime_to_time_t(const HBCI_Date *d,
					  const HBCI_Time *t);
    extern int HBCI_Date_compareTime(const HBCI_Date *d1, const HBCI_Time *t1,
				     const HBCI_Date *d2, const HBCI_Time *t2);
    /*@}*/
#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif
