//	Zinc Application Framework - Z_UTIME.HPP
//	COPYRIGHT (C) 1990-1999.  All Rights Reserved.
//	Zinc Software Incorporated.  Pleasant Grove, Utah  USA

#if !defined(Z_UTIME_HPP)
#define Z_UTIME_HPP
#include <z_fdata.hpp>
#include <z_stdarg.hpp>
#include <z_lang.hpp>

// --------------------------------------------------------------------------
// ----- ZafUTimeData -------------------------------------------------------
// --------------------------------------------------------------------------

#define ZAF_BASIS_YEAR 1950 // The basis year is used for two digit dates.

class ZAF_EXPORT ZafUTimeData : public ZafFormatData
{
public:
	// --- General members ---
	ZafUTimeData(void);
	ZafUTimeData(ZafUInt32 seconds);
	ZafUTimeData(int year, int month, int day, int hour, int minute, int second, int milliSecond);
	ZafUTimeData(const ZafIChar *string, const ZafIChar *format = ZAF_NULLP(ZafIChar));
	ZafUTimeData(const ZafUTimeData &copy);
	virtual ~ZafUTimeData(void);

	// --- Persistence --
	virtual ZafData *Duplicate(void);
#if defined(USE_ZAF_PERSISTENCE)
	ZafUTimeData(const ZafIChar *name, ZafDataPersistence &persist);
	static ZafElement *Read(const ZafIChar *name, ZafDataPersistence &persist);
	virtual void Write(ZafDataPersistence &persist);
#endif

	// --- Attributes & data access ---
	// get
	int BasisYear(void) const;
	int Day(void) const;
	int DayOfWeek(void) const;
	int DaysInMonth(int month = 0) const;
	int DaysInYear(void) const { return (LeapYear() ? 366 : 365); }
	virtual int FormattedText(ZafIChar *buffer, int maxLength, const ZafIChar *format = 0) const;
	int DayOfYear(void) const;
	int Hour(void) const;
	long JulianDay(void) const;
	bool LeapYear(void) const;
	int MilliSecond(void) const;
	int Minute(void) const;
	int Month(void) const;
	int Second(void) const;
	virtual void UTime(int *year, int *month, int *day,
		int *hour, int *minute, int *second,
		int *milliSecond = ZAF_NULLP(int), int *dayOfWeek = ZAF_NULLP(int));
	virtual long Value(void) const;
	int Year(void) const;
	int ZoneOffset(void) const;
	// set
	virtual void Clear(void);
	virtual void GetSystemTime(void);
	virtual ZafError SetBasisYear(int basisYear);
	virtual ZafError SetIncrementUTime(int year, int month, int day, int hour, int minute, int second, int millisecond);
	virtual ZafError SetJulianDay(long jDay);
	virtual ZafError SetUTime(ZafUInt32 seconds);
	virtual ZafError SetUTime(int year, int month, int day, int hour, int minute, int second, int milliSecond);
	virtual ZafError SetUTime(const ZafIChar *buffer, const ZafIChar *format);
	virtual ZafError SetUTime(const ZafUTimeData &number);
	virtual ZafError SetZoneOffset(int zoneOffset);

	virtual void ResetDate(void);
	virtual void ResetTime(void);

	// --- Operators ---
	virtual ZafError Increment(ZafUTimeData *delta);
	virtual ZafError Decrement(ZafUTimeData *delta);
	operator long() { return Value(); }

	ZafUTimeData operator+(const ZafUTimeData &utime2);
	ZafUTimeData operator+(long seconds);
	ZafUTimeData operator-(const ZafUTimeData &utime);
	ZafUTimeData operator-(long seconds);

	ZafUTimeData operator++(void);
	ZafUTimeData operator++(int);
	ZafUTimeData operator--(void);
	ZafUTimeData operator--(int);

	ZafUTimeData &operator=(const ZafUTimeData &utime);
	ZafUTimeData &operator=(long seconds);
	ZafUTimeData &operator+=(const ZafUTimeData &utime);
	ZafUTimeData &operator+=(long seconds);
	ZafUTimeData &operator-=(const ZafUTimeData &utime);
	ZafUTimeData &operator-=(long seconds);

	bool operator<(const ZafUTimeData &utime2);
	bool operator<=(const ZafUTimeData &utime2);
	bool operator>(const ZafUTimeData &utime2);
	bool operator>=(const ZafUTimeData &utime2);
	bool operator==(const ZafUTimeData &utime2);
	bool operator!=(const ZafUTimeData &utime2);

	// --- Class identification ---
	static ZafClassID classID;
	static ZafClassNameChar ZAF_FARDATA className[];
	virtual ZafClassID ClassID(void) const { return (classID); }
	virtual ZafClassName ClassName(void) const { return (className); }
	virtual bool IsA(ZafClassID compareID) const;
	virtual bool IsA(ZafClassName compareName) const;

	static ZafIChar ZAF_FARDATA *DayName(void) { return (dayName); }
	static ZafIChar ZAF_FARDATA *MonthName(void) { return (monthName); }
	static ZafIChar ZAF_FARDATA *TimeName(void) { return (timeName); }

protected:
	// --- General members ---
	void ConvertJDay(int *pYear, int *pMonth, int *pDay, int *pDayOfWeek) const;
	void ConvertUSec(int *hour, int *minute, int *second, int *milliSecond) const;
	long Difference(const ZafUTimeData &utime) const;
	void MakeCanonical(void);

	// printf support
	static void Bind(void);
	static void Format(va_list *argList, ZafIChar **ptrBuffer, ZafIChar fmtch, int flags, int width, int prec);
	static int Parse(va_list *argList, ZafIChar **ptrBuffer, ZafIChar fmtch, int flags, int width, const ZafIChar **fmt);
	int Sprintf(ZafIChar *buffer, int maxLength, const ZafIChar *format) const;
	int Sscanf(const ZafIChar *buffer, const ZafIChar *format);
	int strftime(ZafIChar *buffer, int maxSize, const ZafIChar *format) const;
	ZafIChar *strptime(const ZafIChar *buffer, const ZafIChar *format);

	// --- Language & locale support ---
	ZafLanguageData *dayStrings;
	ZafLanguageData *monthStrings;
	ZafLanguageData *timeStrings;

	static ZafIChar ZAF_FARDATA dayName[];
	static ZafIChar ZAF_FARDATA monthName[];
	static ZafIChar ZAF_FARDATA timeName[];

	int basisYear;
	int zoneOffset;
	long jDay;
	long uSec;
	bool recurse;

#if defined(USE_ZAF_PERSISTENCE)
	// --- Persistence --
	void ReadData(ZafDataPersistence &persist);
	virtual ZafDataConstructor ReadFunction(void) { return (ZafUTimeData::Read); }
	void WriteData(ZafDataPersistence &persist);
#endif

	virtual void Add(const ZafUTimeData &utime);
	virtual void Subtract(const ZafUTimeData &utime);
};

// --- inline functions ---
inline int ZafUTimeData::BasisYear(void) const { return (basisYear); }
inline long ZafUTimeData::JulianDay(void) const { return (jDay); }
inline int ZafUTimeData::ZoneOffset(void) const { return (zoneOffset); }
inline bool ZafUTimeData::operator<(const ZafUTimeData &utime2) { return ((Difference(utime2) < 0) ? true : false); }
inline bool ZafUTimeData::operator<=(const ZafUTimeData &utime2) { return ((Difference(utime2) <= 0) ? true : false); }
inline bool ZafUTimeData::operator>(const ZafUTimeData &utime2) { return ((Difference(utime2) > 0) ? true : false); }
inline bool ZafUTimeData::operator>=(const ZafUTimeData &utime2) { return ((Difference(utime2) >= 0) ? true : false); }
inline bool ZafUTimeData::operator==(const ZafUTimeData &utime2) { return ((Difference(utime2) == 0) ? true : false); }
inline bool ZafUTimeData::operator!=(const ZafUTimeData &utime2) { return ((Difference(utime2) != 0) ? true : false); }
inline ZafUTimeData &ZafUTimeData::operator+=(long seconds) { return (*this += ZafUTimeData(0, 0, 0, 0, 0, (int)seconds, 0)); }
inline ZafUTimeData &ZafUTimeData::operator-=(long seconds) { return (*this -= ZafUTimeData(0, 0, 0, 0, 0, (int)seconds, 0)); }

// --- index members ---
const ZafNumberID ZAF_AM = 1;
const ZafNumberID ZAF_PM = 2;
const ZafNumberID ZAF_TZ = 3;

const ZafNumberID ZAF_DAY_1 = 1;
const ZafNumberID ZAF_DAY_2 = 2;
const ZafNumberID ZAF_DAY_3 = 3;
const ZafNumberID ZAF_DAY_4 = 4;
const ZafNumberID ZAF_DAY_5 = 5;
const ZafNumberID ZAF_DAY_6 = 6;
const ZafNumberID ZAF_DAY_7 = 7;
const ZafNumberID ZAF_SHDAY_1 = ZAF_DAY_7 + 1;
const ZafNumberID ZAF_SHDAY_2 = ZAF_DAY_7 + 2;
const ZafNumberID ZAF_SHDAY_3 = ZAF_DAY_7 + 3;
const ZafNumberID ZAF_SHDAY_4 = ZAF_DAY_7 + 4;
const ZafNumberID ZAF_SHDAY_5 = ZAF_DAY_7 + 5;
const ZafNumberID ZAF_SHDAY_6 = ZAF_DAY_7 + 6;
const ZafNumberID ZAF_SHDAY_7 = ZAF_DAY_7 + 7;
const ZafNumberID ZAF_ABDAY_1 = ZAF_SHDAY_7 + 1;
const ZafNumberID ZAF_ABDAY_2 = ZAF_SHDAY_7 + 2;
const ZafNumberID ZAF_ABDAY_3 = ZAF_SHDAY_7 + 3;
const ZafNumberID ZAF_ABDAY_4 = ZAF_SHDAY_7 + 4;
const ZafNumberID ZAF_ABDAY_5 = ZAF_SHDAY_7 + 5;
const ZafNumberID ZAF_ABDAY_6 = ZAF_SHDAY_7 + 6;
const ZafNumberID ZAF_ABDAY_7 = ZAF_SHDAY_7 + 7;

const ZafNumberID ZAF_MON_1 = 1;
const ZafNumberID ZAF_MON_2 = 2;
const ZafNumberID ZAF_MON_3 = 3;
const ZafNumberID ZAF_MON_4 = 4;
const ZafNumberID ZAF_MON_5 = 5;
const ZafNumberID ZAF_MON_6 = 6;
const ZafNumberID ZAF_MON_7 = 7;
const ZafNumberID ZAF_MON_8 = 8;
const ZafNumberID ZAF_MON_9 = 9;
const ZafNumberID ZAF_MON_10 = 10;
const ZafNumberID ZAF_MON_11 = 11;
const ZafNumberID ZAF_MON_12 = 12;
const ZafNumberID ZAF_SHMON_1 = ZAF_MON_12 + 1;
const ZafNumberID ZAF_SHMON_2 = ZAF_MON_12 + 2;
const ZafNumberID ZAF_SHMON_3 = ZAF_MON_12 + 3;
const ZafNumberID ZAF_SHMON_4 = ZAF_MON_12 + 4;
const ZafNumberID ZAF_SHMON_5 = ZAF_MON_12 + 5;
const ZafNumberID ZAF_SHMON_6 = ZAF_MON_12 + 6;
const ZafNumberID ZAF_SHMON_7 = ZAF_MON_12 + 7;
const ZafNumberID ZAF_SHMON_8 = ZAF_MON_12 + 8;
const ZafNumberID ZAF_SHMON_9 = ZAF_MON_12 + 9;
const ZafNumberID ZAF_SHMON_10 = ZAF_MON_12 + 10;
const ZafNumberID ZAF_SHMON_11 = ZAF_MON_12 + 11;
const ZafNumberID ZAF_SHMON_12 = ZAF_MON_12 + 12;
const ZafNumberID ZAF_ABMON_1 = ZAF_SHMON_12 + 1;
const ZafNumberID ZAF_ABMON_2 = ZAF_SHMON_12 + 2;
const ZafNumberID ZAF_ABMON_3 = ZAF_SHMON_12 + 3;
const ZafNumberID ZAF_ABMON_4 = ZAF_SHMON_12 + 4;
const ZafNumberID ZAF_ABMON_5 = ZAF_SHMON_12 + 5;
const ZafNumberID ZAF_ABMON_6 = ZAF_SHMON_12 + 6;
const ZafNumberID ZAF_ABMON_7 = ZAF_SHMON_12 + 7;
const ZafNumberID ZAF_ABMON_8 = ZAF_SHMON_12 + 8;
const ZafNumberID ZAF_ABMON_9 = ZAF_SHMON_12 + 9;
const ZafNumberID ZAF_ABMON_10 = ZAF_SHMON_12 + 10;
const ZafNumberID ZAF_ABMON_11 = ZAF_SHMON_12 + 11;
const ZafNumberID ZAF_ABMON_12 = ZAF_SHMON_12 + 12;

#endif // Z_UTIME_HPP

