#include <sstream>
#include <iostream>
#include <string>
#include "TStringList.h"

// include BipDATE only one time
#ifndef _BipDATE_
#define _BipDATE_

class TDateTime
{
	private:
		time_t tTDateTime;			// store the date
		String sBP_Format;		// store the format of the date
		bool bBP_Null;				// true if date is null
		int iBPError;				// store error code

	public:
		TDateTime (); // constructor
		void EncodeDateTime (const int BPyear, const int BPmonth, const int BPday,
			  const int BPhour, const int BPmin, const int BPsec, const int msec);		
		void set (const String BPdate);
		String str (void);
		int geterror (void);
		void SetFormat (const String BPformat);
		String FormatString(const String BPformat);
		String getformat (void);
		void settimet (time_t BPtimet);
		time_t gettimet (void);
		int day (void);
		int month (void);
		int year (void);
		int hour (void);
		int minute (void);
		int second (void);
		bool isnull (void);
		void setnull (void);
		void reset (void);
		int JourJulien(void);
};
TDateTime EncodeDateTime (const time_t timestamp_unix);
TDateTime EncodeDateTime (const int BPyear, const int BPmonth, const int BPday, const int BPhour, const int BPmin, const int BPsec, const int msec);	
TDateTime EncodeDateTime (const int BPyear, const int BPjour_julien, const int BPhour);
TDateTime Now();
TDateTime IncSecond(TDateTime date, int nb_secondes);
TDateTime IncMinute(TDateTime date, int nb_minutes);
TDateTime IncHour(TDateTime date, int nb_heures);
TDateTime IncDay(TDateTime date, int nb_jours);
int       DaysBetween(TDateTime date1, TDateTime date2);
int       NbHeuresEntre(TDateTime date1, TDateTime date2);
int       HoursBetween(TDateTime date1, TDateTime date2);
int       SecondsBetween(TDateTime date1, TDateTime date2);
void      Sleep(unsigned int nb_millisecondes);
short     ComparerDates(TDateTime date1, TDateTime date2);

unsigned short DayOfTheWeek(TDateTime date);	// Retourne le jour de la semaine : 1 pour lundi, 2 pour mardi... 7 pour dimanche
int DayOfTheYear(TDateTime date);

TDateTime DecalageTU_HeureLocale(TDateTime jour);   // Retourne la date fournie en Temps Universel, en Heure Locale
TDateTime DecalageHeureLocale_TU(TDateTime jour);   // Retourne la date fournie en Heure Locale, en Temps Universel

// error codes for TDateTime::iBPError (also return by TDateTime::geterror() )
//
//  0 = non error
//  1 = day is bad
//  2 = month is bad
//  3 = year is bad
//  4 = hour is bad
//  5 = minute is bad
//  6 = second is bad
//  7 = input date is bad
//  8 = date is empty
//  9 = format is empty



//-----------------------------------------------------------------
//!    TDateTime::TDateTime : class constructor                       !
//-----------------------------------------------------------------
//! return : none                                                 !
//-----------------------------------------------------------------
TDateTime::TDateTime ()
{
	// reset date
	tTDateTime = 0;
	bBP_Null = true;

	// reset format
	sBP_Format = "";

	// reset error code
	iBPError = 0;

}



//-----------------------------------------------------------------
//!    TDateTime::reset : reset date and format                     !
//-----------------------------------------------------------------
//! return : none                                                 !
//-----------------------------------------------------------------
//! rem : date is set to null and format to ""                    !
//-----------------------------------------------------------------
void TDateTime::reset (void)
{
	// set date to 0
	tTDateTime = 0;
	bBP_Null = true;

	// format is null
	sBP_Format = "";

	// reset error code
	iBPError = 0;

}



//-----------------------------------------------------------------
//!    TDateTime::setdatetime : fill date and time into a BP_date   !
//!                           container                           !
//-----------------------------------------------------------------
//! BPyear : year (min 1970, max 2038)                            !
//! BPmonth : month (min 1, max 12)                               !
//! BPday : day (min 1, max 31)                                   !
//! BPhour : hour (min 0, max 23)                                 !
//! BPmin : minute (min 0, max 59)                                !
//! BPsec : second (min 0, max 59)                                !
//!																  !
//! return : none                                                 !
//-----------------------------------------------------------------
//! if error occurs, the date is set to null and                  !
//!     TDateTime::geterror() return error code                     !
//-----------------------------------------------------------------
//! minimum date : 1 january 1970  0 hour 0 minute 0 second       !
//! maximum date : 19 january 2038  3 hours 14 minutes 7 seconds  !
//! rem : the min and max hour depends on the GMT+- local time    !
//-----------------------------------------------------------------
void TDateTime::EncodeDateTime (const int BPyear, const int BPmonth, const int BPday,
			  const int BPhour, const int BPmin, const int BPsec, const int msec)
{

	tm tmBPStruct;
	
	// reset error code
	iBPError = 0;

	// verify input values
	if (BPday < 1 || BPday > 31)
		iBPError = 1;

	if (BPmonth < 1 || BPmonth > 12)
		iBPError = 2;

	if (BPyear < 1970 || BPyear > 2038)
		iBPError = 3;

	if (BPhour < 0 || BPhour > 24)
		iBPError = 4;

	if (BPmin < 0 || BPmin > 59)
		iBPError = 5;

	if (BPsec < 0 || BPsec > 59)
		iBPError = 6;

	// if ok, store date and time
	if (iBPError == 0)
	{
		tmBPStruct.tm_isdst = -1;
		tmBPStruct.tm_sec = BPsec;
		tmBPStruct.tm_min = BPmin;
		tmBPStruct.tm_hour = BPhour; 
		tmBPStruct.tm_mday = BPday;
		tmBPStruct.tm_mon = BPmonth - 1;
		tmBPStruct.tm_year = BPyear - 1900;
		tmBPStruct.tm_wday = 0;
		tmBPStruct.tm_yday = 0;

		TDateTime::tTDateTime = mktime(&tmBPStruct);

		// date is bad
		if (tTDateTime == (time_t)-1)
		{
			iBPError = 7;

			// set date to null
			TDateTime::setnull ();
		}
		else
			// date  is not null
			bBP_Null = false;
	}
	else
	{
		// set date to null
		TDateTime::setnull ();
	}
}

//-----------------------------------------------------------------
//!    TDateTime::set : fill formated date and time into a BP_date  !
//!                           container                           !
//-----------------------------------------------------------------
//! BPdate : formated date and/or time                            !
//! rem : the formated date/time must have the same order than    !
//!    the format. the numeric values must be separated by a non  !
//!    numeric separator.
//!																  !
//! return : none                                                 !
//-----------------------------------------------------------------
//! if error occurs, the date is set to null and                  !
//!     TDateTime::geterror() return error code                     !
//-----------------------------------------------------------------
//! see TDateTime::setdatetime for max and min date                 !
//-----------------------------------------------------------------
//! warning : TDateTime::set try to detect the content of the input !
//!    String, but some format can fail,                          !
//!    TDateTime::setdatetime is more secure                        !
//-----------------------------------------------------------------
void TDateTime::set (const String BPdate)
{
	int BPyear;
	int BPmonth;
	int BPday;
	int BPhour;
	int BPmin;
	int BPsec;
	int iBegin;
	int iEnd;
	int iValue;
	int iValueBegin;
	int iValueEnd;
	String sString;
	String sFormat;
	String sCommand;
	String sValue;


	// reset error code
	iBPError = 0;

	// verify input String
	if (BPdate == "")
		iBPError = 8;

	// verify format
	if (sBP_Format == "")
		iBPError = 9;


	if (iBPError == 0)
	{
		BPyear = 0;
		BPmonth = 0;
		BPday = 0;
		BPhour = 0;
		BPmin = 0;
		BPsec = 0;

		// explore input String :
		sFormat = TDateTime::sBP_Format;

		iBegin = 0;
		iValueBegin = 0;
		while (iBegin < sFormat.length() && iValueBegin < BPdate.length())
		{
			// search for date/time command into format String
			sString = "";
			iEnd = iBegin;
			while (sFormat [iEnd] != 'd' &&
				   sFormat [iEnd] != 'm' &&
				   sFormat [iEnd] != 'y' &&
				   sFormat [iEnd] != 'h' &&
				   sFormat [iEnd] != 'n' &&
	   			   sFormat [iEnd] != 's' &&
				   iEnd < sFormat.length())
			{
				if (sFormat [iEnd] == '!')
					iEnd++;
				sString += sFormat [iEnd];
				iEnd++;
			}


			// search full command
			iBegin = iEnd;
			iEnd++;
			while (sFormat [iEnd] == sFormat [iBegin] &&
				   iEnd < sFormat.length())
			{
				iEnd++;
			}

			// store command
			sCommand = sFormat.substr(iBegin, iEnd - iBegin);

			// search numeric value into input String
			iValueEnd = iValueBegin;
			while ((BPdate [iValueEnd] < '0' || BPdate [iValueEnd] > '9')
				   && iValueEnd < BPdate.length())
			{
				iValueEnd++;
			}

			// retreive full numeric value
			iValueBegin = iValueEnd;
			iValueEnd++;
			while ((BPdate [iValueEnd] >= '0' && BPdate [iValueEnd] <= '9')
				   && iValueEnd < BPdate.length())
			{
				iValueEnd++;
			}

			// store value into integer
			sValue = BPdate.substr(iValueBegin, iValueEnd - iValueBegin);
			std::istringstream sStream (sValue);
			sStream >> iValue;

			// interpret command
			if (sCommand == "d" || sCommand == "dd")
				BPday = iValue;
			else if (sCommand == "m" || sCommand == "mm")
				BPmonth = iValue;
			else if (sCommand == "yy")
			{
				if (iValue < 38)
					BPyear = iValue + 2000;
				else if (iValue < 500)
					BPyear = iValue + 1900;
				else
					BPyear = iValue;
			}
			else if (sCommand == "yyyy")
				BPyear = iValue;
			else if (sCommand == "h" || sCommand == "hh")
				BPhour = iValue;
			else if (sCommand == "n" || sCommand == "nn")
				BPmin = iValue;
			else if (sCommand == "s" || sCommand == "ss")
				BPsec = iValue;

			iBegin = iEnd;
			iValueBegin = iValueEnd;

		}

		// date is not null
		bBP_Null = false;

		// store date and/or time
		EncodeDateTime (BPyear, BPmonth, BPday, BPhour, BPmin, BPsec, 0);

	}
	else
	{
		// set date to null
		TDateTime::setnull ();
	}

}



//-----------------------------------------------------------------
//!    TDateTime::geterror : return error code                      !
//-----------------------------------------------------------------
//! return : error code or 0 if none                              !
//-----------------------------------------------------------------
int TDateTime::geterror (void)
{
	return iBPError;

}


//-----------------------------------------------------------------
//!    TDateTime::str : return date and time into a String          !
//!                        depending on format                    !
//-----------------------------------------------------------------
//! return : String or "" if date is null                         !
//-----------------------------------------------------------------
//! use TDateTime::SetFormat before TDateTime::str                    !
//! if error occurs, the return String = "" and                   !
//!     TDateTime::geterror() return error code                     !
//-----------------------------------------------------------------
String TDateTime::str (void)
{
	std::ostringstream os;

	tm *tmBPStruct;
	time_t tBPtime;
	int iBegin;
	int iEnd;
	String sFormat;
	String sString;
	String sCommand;


	// reset error code
	iBPError = 0;

	// return "" if date is null
	if (bBP_Null == true)
		return "";
	
	// transfert datetime and format
	tBPtime = tTDateTime;
	sFormat = sBP_Format;

	// date too big or too small
	if (tBPtime == (time_t)-1)
	{
		iBPError = 7;
		return "";
	}

	// date is empty
	if (tBPtime == (time_t)0)
	{
		iBPError = 8;
		return "";
	}

	// format is empty
	if (sFormat == "")
	{
		iBPError = 9;
		return "";
	}

	// convert into time structure
	tmBPStruct = localtime(&tBPtime);


	// construct output stringstream
	iBegin = 0;
	while (iBegin < sFormat.length())
	{
		// search for date/time command
		sString = "";
		iEnd = iBegin;
		while (sFormat [iEnd] != 'd' &&
			   sFormat [iEnd] != 'm' &&
			   sFormat [iEnd] != 'y' &&
			   sFormat [iEnd] != 'h' &&
			   sFormat [iEnd] != 'n' &&
   			   sFormat [iEnd] != 's' &&
			   iEnd < sFormat.length())
		{
			if (sFormat [iEnd] == '!')
				iEnd++;
			sString += sFormat [iEnd];
			iEnd++;
		}

		// copy leading character
		if (iEnd > iBegin)
			os << sString;

		// search full command
		iBegin = iEnd;
		iEnd++;
		while (sFormat[iEnd] == sFormat[iBegin] &&
			   iEnd < sFormat.length())
		{
			iEnd++;
		}

		// interpret command
		sCommand = sFormat.substr(iBegin, iEnd - iBegin);

		// day
		if (sCommand == "d")
			os << tmBPStruct->tm_mday;
		else if (sCommand == "dd")
		{
			if (tmBPStruct->tm_mday < 10)
				os << "0";
			os << tmBPStruct->tm_mday;
		}
		// month
		else if (sCommand == "m")
			os << tmBPStruct->tm_mon + 1;
		else if (sCommand == "mm")
		{
			if (tmBPStruct->tm_mon < 9)
				os << "0";
			os << tmBPStruct->tm_mon + 1;
		}
		// year
		else if (sCommand == "yy")
		{
			if (tmBPStruct->tm_year < 100)
				os << tmBPStruct->tm_year;
			else
			{
				if (tmBPStruct->tm_year < 110)
					os << '0';
				os << tmBPStruct->tm_year - 100;
			}
		}
		else if (sCommand == "yyyy")
			os << tmBPStruct->tm_year + 1900;
		// hour
		else if (sCommand == "h")
			os << tmBPStruct->tm_hour;
		else if (sCommand == "hh")
		{
			if (tmBPStruct->tm_hour < 10)
				os << "0";
			os << tmBPStruct->tm_hour;
		}
		// minute
		else if (sCommand == "n")
			os << tmBPStruct->tm_min;
		else if (sCommand == "nn")
		{
			if (tmBPStruct->tm_min < 10)
				os << "0";
			os << tmBPStruct->tm_min;
		}
		// second
		else if (sCommand == "s")
			os << tmBPStruct->tm_sec;
		else if (sCommand == "ss")
		{
			if (tmBPStruct->tm_sec < 10)
				os << "0";
			os << tmBPStruct->tm_sec;
		}

		iBegin = iEnd;
	}

	return os.str();

}


//-----------------------------------------------------------------
String TDateTime::FormatString(const String BPformat)
{
	SetFormat(BPformat);
	return str();
}


//-----------------------------------------------------------------
//!    TDateTime::SetFormat : set the format for the date           !
//!                         use by TDateTime::str                   !
//-----------------------------------------------------------------
//! BPformat : String containing description of the format        !
//!                                                               !
//! command :                                                     !
//! d  = number of the day (ie : 1)                               !
//! dd = number of the day, 2 chars (ie : 01)                     !
//! m  = number of the month (ie : 2)                             !
//! mm = number of the month, 2 chars (ie : 02)                   !
//! yy = number of the year, 2 chars (ie : 99)                    !
//! yyyy = number of the year, 4 chars (ie : 1999)                !
//! h  = number of the hour (ie : 3)                              !
//! hh = number of the hour, 2 chars (ie : 03)                    !
//! n  = number of the minute (ie : 4)                            !
//! nn = number of the minute, 2 chars (ie : 04)                  !
//! s  = number of the second (ie : 5)                            !
//! ss = number of the second, 2 chars (ie : 05)                  !
//! !x = print the character x (ie : !d give "d")                 !
//! other = all the other character stay unmodified               !
//!                                                               !
//! samples :                                                     !
//! "dd/mm/yyyy hh:nn:ss" give "01/02/2004 08:09:01"              !
//! "m/d/yy h:n:s" give "12/31/99 1:2:15"                         !
//! "d/m/yy" give "31/12/04"                                      !
//! "hh:nn" give "08:01"                                          !
//! "tod!ay is : d mm yyyy" give "today is : 1 03 2004"           !
//!                                                               !
//! return : none                                                 !
//-----------------------------------------------------------------
//!     TDateTime::geterror() return error code                     !
//-----------------------------------------------------------------
void TDateTime::SetFormat (const String BPformat)
{

	// reset error code
	iBPError = 0;

	// verify format
	if (BPformat == "")
	{
		iBPError = 9;
	}
	else
	{
		// store the format
		sBP_Format = BPformat;
	}

}



//-----------------------------------------------------------------
//!    TDateTime::getformat : return the format for the date        !
//-----------------------------------------------------------------
//! return : String containing the format in use                  !
//-----------------------------------------------------------------
String TDateTime::getformat (void)
{

	// reset error code
	iBPError = 0;

	return sBP_Format;

}



//-----------------------------------------------------------------
//!    TDateTime::day : return the day                              !
//-----------------------------------------------------------------
//! return : integer containing the day of the date (1-31)        !
//!           or -1 if null                                       !
//-----------------------------------------------------------------
int TDateTime::day (void)
{

	tm *tmBPStruct;

	// reset error code
	iBPError = 0;

	// if date is not null
	if (bBP_Null == true)
	{
		return -1;
	}
	else
	{
		// convert date into time structure
		tmBPStruct = localtime(&tTDateTime);

		return tmBPStruct->tm_mday;
	}

}



//-----------------------------------------------------------------
//!    TDateTime::month : return the month                          !
//-----------------------------------------------------------------
//! return : integer containing the month of the date (1-12)      !
//!           or -1 if null                                       !
//-----------------------------------------------------------------
int TDateTime::month (void)
{

	tm *tmBPStruct;

	// reset error code
	iBPError = 0;

	// if date is not null
	if (bBP_Null == true)
	{
		return -1;
	}
	else
	{
		// convert date into time structure
		tmBPStruct = localtime(&tTDateTime);

		return tmBPStruct->tm_mon + 1;
	}

}



//-----------------------------------------------------------------
//!    TDateTime::year : return the year                            !
//-----------------------------------------------------------------
//! return : integer containing the year of the date (1970-2038)  !
//!           or -1 if null                                       !
//-----------------------------------------------------------------
int TDateTime::year (void)
{

	tm *tmBPStruct;

	// reset error code
	iBPError = 0;

	// if date is not null
	if (bBP_Null == true)
	{
		return -1;
	}
	else
	{
		// convert date into time structure
		tmBPStruct = localtime(&tTDateTime);

		return tmBPStruct->tm_year + 1900;
	}

}



//-----------------------------------------------------------------
//!    TDateTime::hour : return the hour                            !
//-----------------------------------------------------------------
//! return : integer containing the hour of the date (0-23)       !
//!           or -1 if null                                       !
//-----------------------------------------------------------------
int TDateTime::hour (void)
{

	tm *tmBPStruct;

	// reset error code
	iBPError = 0;

	// if date is not null
	if (bBP_Null == true)
	{
		return -1;
	}
	else
	{
		// convert date into time structure
		tmBPStruct = localtime(&tTDateTime);

		return tmBPStruct->tm_hour;
	}

}



//-----------------------------------------------------------------
//!    TDateTime::minute : return the minute                        !
//-----------------------------------------------------------------
//! return : integer containing the minute of the date (0-59)     !
//!           or -1 if null                                       !
//-----------------------------------------------------------------
int TDateTime::minute (void)
{

	tm *tmBPStruct;

	// reset error code
	iBPError = 0;

	// if date is not null
	if (bBP_Null == true)
	{
		return -1;
	}
	else
	{
		// convert date into time structure
		tmBPStruct = localtime(&tTDateTime);

		return tmBPStruct->tm_min;
	}

}



//-----------------------------------------------------------------
//!    TDateTime::second : return the second                        !
//-----------------------------------------------------------------
//! return : integer containing the second of the date (0-59)     !
//!           or -1 if null                                       !
//-----------------------------------------------------------------
int TDateTime::second (void)
{

	tm *tmBPStruct;

	// reset error code
	iBPError = 0;

	// if date is not null
	if (bBP_Null == true)
	{
		return -1;
	}
	else
	{
		// convert date into time structure
		tmBPStruct = localtime(&tTDateTime);

		return tmBPStruct->tm_sec;
	}

}



//-----------------------------------------------------------------
//!    TDateTime::settimet : set the time from time_t container     !
//-----------------------------------------------------------------
//! return : none                                                 !
//-----------------------------------------------------------------
void TDateTime::settimet (time_t BPtimet)
{

	// reset error code
	iBPError = 0;

	tTDateTime = BPtimet;

}



//-----------------------------------------------------------------
//!    TDateTime::gettimet : return the time in time_t container    !
//-----------------------------------------------------------------
//! return : time_t containing the date                           !
//-----------------------------------------------------------------
time_t TDateTime::gettimet (void)
{

	// reset error code
	iBPError = 0;

	return tTDateTime;

}



//-----------------------------------------------------------------
//!    TDateTime::isnull : return true if date is null              !
//!                           else return false                   !
//-----------------------------------------------------------------
//! return : bool                                                 !
//-----------------------------------------------------------------
bool TDateTime::isnull (void)
{

	// reset error code
	iBPError = 0;

	if (bBP_Null == true)
		return true;
	else
		return false;

}



//-----------------------------------------------------------------
//!    TDateTime::setnull : set date to null value                  !
//-----------------------------------------------------------------
//! return : none                                                 !
//-----------------------------------------------------------------
void TDateTime::setnull (void)
{

	// reset error code
	iBPError = 0;

	tTDateTime = 0;
	bBP_Null = true;

}

//-----------------------------------------------------------------
TDateTime EncodeDateTime (const time_t timestamp_unix)
{
TDateTime date_temp;
int BPyear, BPmonth, BPday, BPhour, BPmin, BPsec;
struct tm *ptm;
char chartime[5];
ptm = localtime(&timestamp_unix);

strftime(chartime, 5, "%Y", ptm);
valueOf(chartime, BPyear);
strftime(chartime, 5, "%m", ptm);
valueOf(chartime, BPmonth);
strftime(chartime, 5, "%d", ptm);
valueOf(chartime, BPday);
strftime(chartime, 5, "%H", ptm);
valueOf(chartime, BPhour);
strftime(chartime, 5, "%M", ptm);
valueOf(chartime, BPmin);
strftime(chartime, 5, "%S", ptm);
valueOf(chartime, BPsec);

date_temp.EncodeDateTime(BPyear, BPmonth, BPday, BPhour, BPmin, BPsec, 0);
return date_temp;
}

//-----------------------------------------------------------------
TDateTime EncodeDateTime (const int BPyear, const int BPmonth, const int BPday, const int BPhour, const int BPmin, const int BPsec, const int msec)
{
	TDateTime date_temp;
	date_temp.EncodeDateTime(BPyear, BPmonth, BPday, BPhour, BPmin, BPsec, msec);
	return date_temp;
}

//-----------------------------------------------------------------
TDateTime EncodeDateTime (const int BPyear, const int BPjour_julien, const int BPhour)
{
	TDateTime date_temp;
	int mois_approx;
	mois_approx = BPjour_julien/30;
	if(mois_approx<1)
		mois_approx = 1;
	else if(mois_approx>12)
		mois_approx = 12;
	date_temp = EncodeDateTime(BPyear, mois_approx, 1, BPhour, 0, 0, 0);
	while(date_temp.JourJulien()!=BPjour_julien)
		date_temp = IncDay(date_temp,1);
	date_temp = EncodeDateTime(BPyear, date_temp.month(), date_temp.day(), BPhour, 0, 0, 0);
	return date_temp;
}

//-----------------------------------------------------------------
TDateTime IncHour(TDateTime date, int nb_heures)
{
	int h;
	int annee, mois, jour, heure, minute, seconde;
	TDateTime date_temp, date_temp1;
	
	if(nb_heures>0)
	{
		for(h=0;h<nb_heures;h++)
		{
			annee = date.year();
			mois = date.month();
			jour = date.day();
			heure = date.hour();
			minute = date.minute();
			seconde = date.second();
			
			date_temp.EncodeDateTime(annee,mois,jour,heure+1,minute,seconde,0);
			if(date_temp.isnull())
			{
				date_temp.EncodeDateTime(annee,mois,jour+1,1,minute,seconde,0);
				if(date_temp.isnull())
				{
					date_temp.EncodeDateTime(annee,mois+1,1,0,minute,seconde,0);
					if(date_temp.isnull())
						date_temp.EncodeDateTime(annee+1,1,1,0,minute,seconde,0);
				}
			}
			date = date_temp;
		}
	}
	if(nb_heures<0)
	{
		for(h=nb_heures;h<0;h++)
		{
			annee = date.year();
			mois = date.month();
			jour = date.day();
			heure = date.hour();
			minute = date.minute();
			seconde = date.second();
		    
			if(heure>=1)
			{
			    date.EncodeDateTime(annee,mois,jour,heure-1,minute,seconde,0);
				// Les 5 lignes suivantes sont la pour corriger le bug du passage a l'heure d'ete ou d'hiver
				// En effet, l'appel de EncodeDateTime(2005,3,27,2,0,0,0) renvoie 27/03/2005 3h ! 
				date_temp.EncodeDateTime(annee,mois,jour,heure,minute,seconde,0);
			    if((date.isnull())||(date.FormatString("dd/mm/yyyy hh:nn")==date_temp.FormatString("dd/mm/yyyy hh:nn")))
			    {
			    	date.EncodeDateTime(annee,mois,jour,heure-2,minute,seconde,0);
			    	h++;
			    }
			}
            else
            {
            	if(jour>1)                            
                	date.EncodeDateTime(annee,mois,jour-1,23,minute,seconde,0);
                else
			    {
                	mois=mois-1;
                    if(mois==0)
                    	date.EncodeDateTime(annee-1,12,31,23,minute,seconde,0);
                    else
                    {
                    	if((mois==1)||(mois==3)||(mois==5)||(mois==7)||(mois==8)||(mois==10)||(mois==12))
                        	date.EncodeDateTime(annee,mois,31,23,minute,seconde,0);
                        if((mois==4)||(mois==6)||(mois==9)||(mois==11))
                            date.EncodeDateTime(annee,mois,30,23,minute,seconde,0);
                        if(mois==2)
                        {
                        	date_temp.EncodeDateTime(annee,2,29,23,minute,seconde,0);
                            date_temp1.EncodeDateTime(annee,3,1,23,minute,seconde,0);
                            if(date_temp1.FormatString("dd/mm/yyyy hh:nn")==date_temp.FormatString("dd/mm/yyyy hh:nn"))
                            	date.EncodeDateTime(annee,2,28,23,minute,seconde,0);
                            else
                            	date = date_temp;
                        }
                    }
			  	}
			}
		}
	}
	
	return date;
}

//-----------------------------------------------------------------
TDateTime IncMinute(TDateTime date, int nb_minutes)
{
	int h;
	int annee, mois, jour, heure, minute, seconde;
	TDateTime date_temp, date_temp1;
	
	if(nb_minutes>0)
	{
		for(h=0;h<nb_minutes;h++)
		{
			annee = date.year();
			mois = date.month();
			jour = date.day();
			heure = date.hour();
			minute = date.minute();
			seconde = date.second();
			
			date_temp.EncodeDateTime(annee,mois,jour,heure,minute+1,seconde,0);
			if(date_temp.isnull())
			{
				date_temp.EncodeDateTime(annee,mois,jour,heure+1,0,seconde,0);
				if(date_temp.isnull())
				{
					date_temp.EncodeDateTime(annee,mois,jour+1,1,0,seconde,0);
					if(date_temp.isnull())
					{
						date_temp.EncodeDateTime(annee,mois+1,1,0,minute,seconde,0);
						if(date_temp.isnull())
							date_temp.EncodeDateTime(annee+1,1,1,0,minute,seconde,0);
					}
				}
			}
			date = date_temp;
		}
	}
	if(nb_minutes<0)
	{
		for(h=nb_minutes;h<0;h++)
		{
			annee = date.year();
			mois = date.month();
			jour = date.day();
			heure = date.hour();
			minute = date.minute();
			seconde = date.second();
		    
			if(minute>0)
			    date.EncodeDateTime(annee,mois,jour,heure,minute-1,seconde,0);
            else
            {
            	if(heure>0)
            	{
            		date.EncodeDateTime(annee,mois,jour,heure-1,59,seconde,0);
					// Les 5 lignes suivantes sont la pour corriger le bug du passage a l'heure d'ete ou d'hiver
					// En effet, l'appel de EncodeDateTime(2005,3,27,2,0,0,0) renvoie 27/03/2005 3h ! 
					// ATTENTION, CELA NE CORRIGE PAS LE BUG !!!!!!!!!!!!! ====================================================<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
					date_temp.EncodeDateTime(annee,mois,jour,heure,59,seconde,0);
			    	if((date.isnull())||(date.FormatString("dd/mm/yyyy hh:nn")==date_temp.FormatString("dd/mm/yyyy hh:nn")))
			    	{
			    		date.EncodeDateTime(annee,mois,jour,heure-2,59,seconde,0);
			    		h++;
			    	}
            	}
            	else
            	{
            		if(jour>1)                            
                		date.EncodeDateTime(annee,mois,jour-1,23,59,seconde,0);
                	else
			    	{
                		mois=mois-1;
                    	if(mois==0)
	                    	date.EncodeDateTime(annee-1,12,31,23,59,seconde,0);
    	                else
                    	{
                    		if((mois==1)||(mois==3)||(mois==5)||(mois==7)||(mois==8)||(mois==10)||(mois==12))
                        		date.EncodeDateTime(annee,mois,31,23,59,seconde,0);
                        	if((mois==4)||(mois==6)||(mois==9)||(mois==11))
                            	date.EncodeDateTime(annee,mois,30,23,59,seconde,0);
                        	if(mois==2)
                        	{
                        		date_temp.EncodeDateTime(annee,2,29,23,59,seconde,0);
                            	date_temp1.EncodeDateTime(annee,3,1,23,59,seconde,0);
                            	if(date_temp1.FormatString("dd/mm/yyyy hh:nn")==date_temp.FormatString("dd/mm/yyyy hh:nn"))
                            		date.EncodeDateTime(annee,2,28,23,59,seconde,0);
                            	else
                            		date = date_temp;
                        	}
                    	}
					}
			  	}
			}
		}
	}
	
	return date;
}

//-----------------------------------------------------------------
TDateTime IncDay(TDateTime date, int nb_jours)
{
	return IncHour(date, nb_jours*24);
}

//-----------------------------------------------------------------
TDateTime IncSecond(TDateTime date, int nb_secondes)
{	
	date.settimet(date.gettimet()+nb_secondes);
	return date;
}

//-----------------------------------------------------------------
int DaysBetween(TDateTime date1, TDateTime date2)
{
	int nb_jours=0;
	TDateTime datea = IncHour(date1,0);
	while(datea.FormatString("dd/mm/yyyy")!=date2.FormatString("dd/mm/yyyy"))
	{
    	nb_jours++;
		datea=IncDay(date1,nb_jours);
	}
	
	return nb_jours;
}

//-----------------------------------------------------------------
int NbHeuresEntre(TDateTime date1, TDateTime date2)
{
	int nb_heures=0;
	TDateTime date_a, date_b;
	
	date_a = IncHour(date1,0);
	date_b = IncHour(date1,0);
	while((date_a.FormatString("dd/mm/yyyy hh")!=date2.FormatString("dd/mm/yyyy hh"))&&(date_b.FormatString("dd/mm/yyyy hh")!=date2.FormatString("dd/mm/yyyy hh")))
	{
    	nb_heures++;
		date_a=IncHour(date1,nb_heures);
		date_b=IncHour(date1,-nb_heures);
	}
	
	return nb_heures;
}

//-----------------------------------------------------------------
int HoursBetween(TDateTime date1, TDateTime date2)
{
	return NbHeuresEntre(date1, date2);
}

//-----------------------------------------------------------------
int SecondsBetween(TDateTime date1, TDateTime date2)
{
	return fabs(date2.gettimet()-date1.gettimet());
}


//---------------------------------------------------------------------------
// Compare 2 dates
// Si date1 < date2, retour = -1
// Si date1 = date2, retour = 0
// Si date1 > date2, retour = 1
short ComparerDates(TDateTime date1, TDateTime date2)
{
short retour;
long long int d1, d2;
d1 = date1.gettimet();
d2 = date2.gettimet();
if(d1<d2)
        retour = -1;
else if(d1==d2)
        retour = 0;
else retour = 1;
return retour;
}

//-----------------------------------------------------------------
int TDateTime::JourJulien(void)
{
	TDateTime temp;
	int jour, mois, annee, jour_julien;
	
	jour=day();
	mois=month();
	annee=year();
	
	if(mois==2)
		jour_julien = 31;
	else
	{
		temp.EncodeDateTime(annee,2,29,0,0,0,0);
		if(temp.FormatString("dd")=="29")	// C'est que c'est une annee bissextile
			jour_julien=31+29;
		else
			jour_julien=31+28;
		
		if(mois>3)
			jour_julien=jour_julien+31;
		if(mois>4)
			jour_julien=jour_julien+30;
		if(mois>5)
			jour_julien=jour_julien+31;
		if(mois>6)
			jour_julien=jour_julien+30;
		if(mois>7)
			jour_julien=jour_julien+31;
		if(mois>8)
			jour_julien=jour_julien+31;
		if(mois>9)
			jour_julien=jour_julien+30;
		if(mois>10)
			jour_julien=jour_julien+31;
		if(mois>11)
			jour_julien=jour_julien+30;
		if(mois==1)
			jour_julien=0;
	}
	
	jour_julien = jour_julien + jour;
	return jour_julien;
}

//-----------------------------------------------------------------
TDateTime Now()
{
	TDateTime sortie;
    time_t now = time(0); 
    
    tm * ptm = localtime (&now);
    int aa = ptm->tm_year + 1900;
    int mm = ptm->tm_mon + 1;
    int jj = ptm->tm_mday;
    int hh = ptm->tm_hour;
    int nn = ptm->tm_min;
    int ss = ptm->tm_sec;
    
	sortie.EncodeDateTime(aa, mm, jj, hh, nn, ss, 0);
	
	return sortie;
}

//-----------------------------------------------------------------
void Sleep(unsigned int nb_millisecondes)
{
time_t start_time, cur_time;

time(&start_time);
do
{
    time(&cur_time);
}
while((cur_time - start_time) < nb_millisecondes/1000);
}

//-----------------------------------------------------------------
unsigned short DayOfTheWeek(TDateTime date)
{
unsigned short jour, mois, annee, jour_semaine;
int a, y, m, ndate;

annee = date.year();
mois = date.month();
jour = date.day();

// On calcule le jour julien depuis le 24 novembre 4714BC (calendrier grégorien)
a = (14-mois)/12;
y = annee+4800-a;
m = mois+12*a-3;
ndate = jour + ((153*m+2)/5) + 365*y + (y/4) - (y/100) + (y/400) - 32045;

jour_semaine = (ndate)%7 + 1;

return jour_semaine;
}


//-----------------------------------------------------------------
TDateTime DecalageTU_HeureLocale(TDateTime date_TU)
{
TDateTime dernier_dimanche_mars;
TDateTime dernier_dimanche_octobre;
int i,decal;
TDateTime date_HL;
unsigned int date1, date2, date3;

decal=0;

// Hiver : décalage de 1h (dernier dimanche d'octobre)
// Ete :   décalage de 2h (dernier dimanche de mars)

dernier_dimanche_mars.EncodeDateTime(date_TU.year(), 3, 31, 0, 0, 0, 0);
i=1;
while(DayOfTheWeek(dernier_dimanche_mars)!=7)
{
        dernier_dimanche_mars.EncodeDateTime(date_TU.year(), 3, 31-i, 0, 0, 0, 0);
        i++;
}

dernier_dimanche_octobre.EncodeDateTime(date_TU.year(), 10, 31, 0, 0, 0, 0);
i=1;
while(DayOfTheWeek(dernier_dimanche_octobre)!=7)
{
        dernier_dimanche_octobre.EncodeDateTime(date_TU.year(), 10, 31-i, 0, 0, 0, 0);
        i++;
}

valueOf(date_TU.FormatString("yyyymmdd"), date1);
valueOf(dernier_dimanche_mars.FormatString("yyyymmdd"), date2);
valueOf(dernier_dimanche_octobre.FormatString("yyyymmdd"), date3);
if((date1>=date2)&&(date1<date3))      // en été donc
        decal = 2;                     // décalage de 2 h
else									// sinon...
        decal = 1;					// décalage d'1 h !

date_HL = IncHour(date_TU, decal);

return date_HL;
}

//-----------------------------------------------------------------
TDateTime DecalageHeureLocale_TU(TDateTime date_HL)
{
TDateTime dernier_dimanche_mars;
TDateTime dernier_dimanche_octobre;
int i,decal;
TDateTime date_TU;
unsigned int date1, date2, date3;

decal=0;

// Hiver : décalage de 1h (dernier dimanche d'octobre)
// Ete :   décalage de 2h (dernier dimanche de mars)

dernier_dimanche_mars.EncodeDateTime(date_HL.year(), 3, 31, 0, 0, 0, 0);
i=1;
while(DayOfTheWeek(dernier_dimanche_mars)!=7)
{
        dernier_dimanche_mars.EncodeDateTime(date_HL.year(), 3, 31-i, 0, 0, 0, 0);
        i++;
}

dernier_dimanche_octobre.EncodeDateTime(date_HL.year(), 10, 31, 0, 0, 0, 0);
i=1;
while(DayOfTheWeek(dernier_dimanche_octobre)!=7)
{
        dernier_dimanche_octobre.EncodeDateTime(date_HL.year(), 10, 31-i, 0, 0, 0, 0);
        i++;
}

valueOf(date_HL.FormatString("yyyymmdd"), date1);
valueOf(dernier_dimanche_mars.FormatString("yyyymmdd"), date2);
valueOf(dernier_dimanche_octobre.FormatString("yyyymmdd"), date3);
if((date1>=date2)&&(date1<date3))      // en été donc
        decal = -2;                     // décalage de 2 h
else									// sinon...
        decal = -1;					// décalage d'1 h !

date_TU = IncHour(date_HL, decal);

return date_HL;
}

//-----------------------------------------------------------------
int DayOfTheYear(TDateTime date)
{
	return date.JourJulien();
}


#endif /* _BipDATE_ */
