//-< DATEIME.H >-----------------------------------------------------*--------*
// GigaBASE                  Version 1.0         (c) 1999  GARRET    *     ?  *
// (Post Relational Database Management System)                      *   /\|  *
//                                                                   *  /  \  *
//                          Created:     20-Nov-98    K.A. Knizhnik  * / [] \ *
//                          Last update: 10-Dec-98    K.A. Knizhnik  * GARRET *
//-------------------------------------------------------------------*--------*
// Date-time field type
//-------------------------------------------------------------------*--------*

#ifndef __DATETIME_H__
#define __DATETIME_H__

#include "stdtp.h"
#include "class.h"

BEGIN_GIGABASE_NAMESPACE

class GIGABASE_DLL_ENTRY dbDateTime {
    int4 stamp;
  public:
    bool operator == (dbDateTime const& dt) {
	return stamp == dt.stamp;
    }
    bool operator != (dbDateTime const& dt) {
	return stamp != dt.stamp;
    }
    bool operator > (dbDateTime const& dt) {
	return stamp > dt.stamp;
    }
    bool operator >= (dbDateTime const& dt) {
	return stamp >= dt.stamp;
    }
    bool operator < (dbDateTime const& dt) {
	return stamp < dt.stamp;
    }
    bool operator <= (dbDateTime const& dt) {
	return stamp <= dt.stamp;
    }
    int operator - (dbDateTime const& dt) {
	return stamp - dt.stamp;
    }
     int operator + (dbDateTime const& dt) {
	return stamp + dt.stamp;
    }
    static dbDateTime current() {
	return dbDateTime(time(NULL));
    }
    dbDateTime(time_t t) {
	stamp = t;
    }
    dbDateTime() {
	stamp = -1;
    }
    bool isValid() const {
	return stamp != -1;
    }

    time_t asTime_t() { return stamp; }

    void clear() { stamp = -1; }

    dbDateTime(int year, int month, int day,
	       int hour=0, int min=0, int sec = 0)
    {
	struct tm t;
	t.tm_year = year > 1900 ? year - 1900 : year;
	t.tm_mon = month-1;
	t.tm_mday = day;
	t.tm_hour = hour;
	t.tm_min = min;
	t.tm_sec = sec;
	t.tm_isdst = -1;
	stamp = mktime(&t);
    }
    dbDateTime(int hour, int min) {
	stamp = (hour*60+min)*60;
    }

#if HAVE_LOCALTIME_R && !defined(NO_PTHREADS)
    int year() {
	struct tm t;
	return localtime_r((time_t*)&stamp, &t)->tm_year + 1900;
    }
    int month() { // 1..12
	struct tm t;
	return localtime_r((time_t*)&stamp, &t)->tm_mon + 1;
    }
    int day() { // 1..31
	struct tm t;
	return localtime_r((time_t*)&stamp, &t)->tm_mday;
    }
    int dayOfYear() { // 1..366
	struct tm t;
	return localtime_r((time_t*)&stamp, &t)->tm_yday+1;
    }
    int dayOfWeek() { // 1..7
	struct tm t;
	return localtime_r((time_t*)&stamp, &t)->tm_wday+1;
    }
    int hour() { // 0..24
	struct tm t;
	return localtime_r((time_t*)&stamp, &t)->tm_hour;
    }
    int minute() { // 0..59
	struct tm t;
	return localtime_r((time_t*)&stamp, &t)->tm_min;
    }
    int second() { // 0..59
	struct tm t;
	return localtime_r((time_t*)&stamp, &t)->tm_sec;
    }
    char_t* asString(char* buf, int buf_size, char_t const* format = "%c") const {
	struct tm t;
	strftime(buf, buf_size, format, localtime_r((time_t*)&stamp, &t));
	return buf;
    }
    static dbDateTime currentDate() {
	struct tm t;
	time_t curr = time(NULL);
	localtime_r(&curr, &t);;
	t.tm_hour = 0;
	t.tm_min = 0;
	t.tm_sec = 0;
	return dbDateTime(mktime(&t));
    }
#else
    int year() {
	return localtime((time_t*)&stamp)->tm_year + 1900;
    }
    int month() { // 1..12
	return localtime((time_t*)&stamp)->tm_mon + 1;
    }
    int day() { // 1..31
	return localtime((time_t*)&stamp)->tm_mday;
    }
    int dayOfYear() { // 1..366
	return localtime((time_t*)&stamp)->tm_yday+1;
    }
    int dayOfWeek() { // 1..7
	return localtime((time_t*)&stamp)->tm_wday+1;
    }
    int hour() { // 0..24
	return localtime((time_t*)&stamp)->tm_hour;
    }
    int minute() { // 0..59
	return localtime((time_t*)&stamp)->tm_min;
    }
    int second() { // 0..59
	return localtime((time_t*)&stamp)->tm_sec;
    }
    char_t* asString(char_t* buf, int buf_size, char_t const* format = _T("%c")) const {
	STRFTIME(buf, buf_size, format, localtime((time_t*)&stamp));
	return buf;
    }
    static dbDateTime currentDate() {
	time_t curr = time(NULL);
	struct tm* tp = localtime(&curr);;
	tp->tm_hour = 0;
	tp->tm_min = 0;
	tp->tm_sec = 0;
	return dbDateTime(mktime(tp));
    }
#endif

    CLASS_DESCRIPTOR(dbDateTime,
		     (KEY(stamp,INDEXED|HASHED),
		      METHOD(year), METHOD(month), METHOD(day),
		      METHOD(dayOfYear), METHOD(dayOfWeek),
		      METHOD(hour), METHOD(minute), METHOD(second)));

    dbQueryExpression operator == (char_t const* field) {
	dbQueryExpression expr;
	expr = dbComponent(field,_T("stamp")),_T("="),stamp;
	return expr;
    }
    dbQueryExpression operator != (char_t const* field) {
	dbQueryExpression expr;
	expr = dbComponent(field,_T("stamp")),_T("<>"),stamp;
	return expr;
    }
    dbQueryExpression operator < (char_t const* field) {
	dbQueryExpression expr;
	expr = dbComponent(field,_T("stamp")),_T("<"),stamp;
	return expr;
    }
    dbQueryExpression operator <= (char_t const* field) {
	dbQueryExpression expr;
	expr = dbComponent(field,_T("stamp")),_T("<="),stamp;
	return expr;
    }
    dbQueryExpression operator > (char_t const* field) {
	dbQueryExpression expr;
	expr = dbComponent(field,_T("stamp")),_T(">"),stamp;
	return expr;
    }
    dbQueryExpression operator >= (char_t const* field) {
	dbQueryExpression expr;
	expr = dbComponent(field,_T("stamp")),_T(">="),stamp;
	return expr;
    }
    friend dbQueryExpression between(char_t const* field, dbDateTime& from,
				     dbDateTime& till)
    {
	dbQueryExpression expr;
	expr=dbComponent(field,_T("stamp")),_T("between"),from.stamp,_T("and"),till.stamp;
	return expr;
    }

    static dbQueryExpression ascent(char_t const* field) {
	dbQueryExpression expr;
	expr=dbComponent(field,_T("stamp"));
	return expr;
    }
    static dbQueryExpression descent(char_t const* field) {
	dbQueryExpression expr;
	expr=dbComponent(field,_T("stamp")),_T("desc");
	return expr;
    }
};

END_GIGABASE_NAMESPACE

#endif







