/*
**	Command & Conquer Generals(tm)
**	Copyright 2025 Electronic Arts Inc.
**
**	This program is free software: you can redistribute it and/or modify
**	it under the terms of the GNU General Public License as published by
**	the Free Software Foundation, either version 3 of the License, or
**	(at your option) any later version.
**
**	This program 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 General Public License for more details.
**
**	You should have received a copy of the GNU General Public License
**	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/****************************************************************************\

xtime                      Neal Kettler

Improved version of the Wtime library (V->W->X...)

Handles signed times better and dates long
long long after you'll be dead.

\****************************************************************************/

#include <ctype.h>
#include <time.h>
#ifndef _WINDOWS
#include <sys/time.h>
#endif
#include "xtime.h"

static char *DAYS[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};

static char *FULLDAYS[]={"Sunday","Monday","Tuesday","Wednesday","Thursday",
               "Friday","Saturday"};

static char *MONTHS[]={"Jan","Feb","Mar","Apr","May","Jun","Jul",
               "Aug","Sep","Oct","Nov","Dec"};

static char *FULLMONTHS[]={"January","February","March","April","May","June",
               "July","August","September","October","November","December"};


#define IS_LEAP(y) ((y) % 4) == 0 && (! ((y) % 100) == 0 || ((y) % 400) == 0)
#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)


/////////////// Utility functions ///////////////////

//
// Return the daycount since year 0 for the specified date.
// month = 1-12, day = 1-31 year = 0...
//
static sint32 Get_Day(int month, int day, int year)
{
  time_t days;

  static int DaysAtMonth[] =
      {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};

  /* Add up number of straight days + number of leap days + days */
  /* up to the month + the day of month. */

  days = (year * 365) + (year / 4) - (year / 100) + (year / 400) +
      DaysAtMonth[month-1] + day;

  /* If we haven't hit Feb 29, and this is a leap year, we need to */
  /* subtract out the leap day that was added above for this year */

  if (month < 3 && IS_LEAP(year))
      --days;
    return(days);
}



//
// Get the year from a daycount since year 0
// Also get the daycount since the start of the year
//
// Ayecarumba what a pain in the ass!
//
static bit8 Get_Date_From_Day(sint32 days, OUT sint32 &year, OUT sint32 &yday)
{
  //register long int rem;
  register long int y;
  //register const unsigned short int *ip;
 
  if (days <= 365)
  {
    year=0;
    yday=days+1;  // 1 based
    return(TRUE);
  }

  y = 1;
  days-=365;

  days--;  // zero based
 
  //
  // As far as I can tell there's no non-iteritive way to
  //   do this...
  //
  while (days < 0 || days >= (IS_LEAP (y) ? 366 : 365))
  {
    /* Guess a corrected year, assuming 365 days per year.  */
    long int yg = y + days / 365 - (days % 365 < 0);
 
    /* Adjust DAYS and Y to match the guessed year.  */
    days -= ((yg - y) * 365
        + LEAPS_THRU_END_OF (yg - 1)
        - LEAPS_THRU_END_OF (y - 1));
      y = yg;
  }
  year=y;
  yday=days+1;  // 1 based
  return(TRUE);
}


//
// Get the max day of a given month in a given year
//
int Max_Day(int month, int year)
{
  static char dayTable[2][13] = {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
  };
  bit8 isleap=IS_LEAP(year);
  return(dayTable[isleap][month]);
}



/**********************************************************
int main(int argc, char *argv[])
{
  Xtime wtime;
  int month,mday,year,hour,minute,second,day;
  int i;
  int dayoffset;
  int yr;
  int yday;
  int ydaycount;

  wtime.set(719528,0);

***********************************************
  for (year=0; year<10000; year++)
  {
    ydaycount=1;
    for (month=1; month<=12; month++)
    {
      for (day=1; day<=Max_Day(month,year); day++)
      {
        dayoffset=Get_Day(month,day,year);
        assert (GetDateFromDay(dayoffset,yr,yday)==TRUE);

        //printf("Yday=%d YdayCount=%d\n",yday,ydaycount);

        if (yr!=year)
        {
          printf("MO=%d  DAY=%d  YEAR=%d  YR=%d\n",month,day,year,yr);
          assert(0);
        }
        if (yday != ydaycount)
        {
          printf("MO=%d  DAY=%d  YEAR=%d  YR=%d\n",month,day,year,yr);
          printf("Yday=%d YdayCount=%d\n",yday,ydaycount);
          assert(0);
        }
        ydaycount++;
      }
    } 
    printf("(%d) ",year);
  }
***************************************

  ///////wtime.addSeconds((60*60*24)-(60*60*8));
  ////////wtime.addSeconds(-(60*60*8));  // timezone delta

  dayoffset=Get_Day(1,1,1970);
  printf("DAYOFFSET = %d\n",dayoffset);


  wtime.getTime(month, mday, year, hour, minute, second);
  printf("\n%s %d  %d  %d:%02d:%02d\n\n",
    MONTHS[month-1],mday,year,hour,minute,second);

  struct  timeval   unixtime;
  struct  timezone  unixtzone;
  time_t    ttime;
  tm        tmtime;

  memset(&tmtime,0,sizeof(tmtime));
  ttime=0;
  unixtime.tv_sec=0;
  unixtime.tv_usec=0;

  //gettimeofday(&unixtime,&unixtzone);
  //ttime=time(NULL);
  tmtime=*gmtime(&ttime);

  printf("TIME->CTIME = %s\n",ctime(&ttime));
  printf("GTOD->CTIE = %s\n",ctime(&(unixtime.tv_sec)));
  printf("TIME->GMT->ASCTIME = %s\n",asctime(&tmtime));
}
***************************************************************/



//
// Construct with current clock time
//
Xtime::Xtime(void)
{
  update();
}

//
// Copy constructor
//
Xtime::Xtime( Xtime &other )
{
  day_=other.day_;
  msec_=other.msec_;
}

//
// Set to a time_t (1970-2038)
//
Xtime::Xtime( time_t other )
{
  day_=719528;  // days from year 0 to Jan1, 1970
  // Add seconds from time_t
  addSeconds(other);
  msec_=0;
}

Xtime::~Xtime()
{
}

//
// Add some number of seconds to the time (seconds can be negative)
//
void Xtime::addSeconds(sint32 seconds)
{
  // Add to day counter first
  day_+=(seconds/86400);
  msec_+=(seconds % 86400)*1000;

  // Now normalize in case msec is > 1 days worth
  normalize();
}

//
// If msec is > 1 days worth, adjust the day count
//   & decrement the msec counter until OK.
//
void Xtime::normalize(void)
{
  day_+=(msec_/86400000);
  msec_%=86400000;
 
  while (msec_ < 0)
  {
    day_--;
    msec_+=86400000;
  }
}

//
// Update time to hold the current clock time
// (breaks in 2038 :-)
//
void Xtime::update(void)
{
  day_=719528;  // day_s from year 0 to Jan1, 1970
  msec_=0;

 #ifdef _WINDOWS
  struct _timeb    wintime;
  _ftime(&wintime);
  addSeconds(wintime.time);
  msec_+=wintime.millitm;
 #endif
 #ifndef _WINDOWS
  struct timeval   unixtime;
  struct timezone  unixtzone;
  gettimeofday(&unixtime,&unixtzone);
  addSeconds(unixtime.tv_sec);
  msec_+=(unixtime.tv_usec/1000);
 #endif

  // Now normalize in case msec is > 1 days worth
  normalize();
}


// This takes the standard Microsoft time formatting string
// make sure the out string is big enough
// An example format would be "mm/dd/yy hh:mm:ss"
// CHANGE:  Joe Howes  06/30/99
// To specify 12-hour format, use "aa" instead of "hh".
// The hours will be 12 hour and the string will be
// appended with " AM" or " PM".
bit8 Xtime::FormatTime(char *out, char *format)
{
  int lastWasH=0;
  int ampmflag = 0;
  out[0]=0;
  char *ptr=format;
 
  if (*ptr=='"') ptr++;  // skip past open quote if exists
 
  while (*ptr!=0)
  {
    if (lastWasH>0)
      lastWasH--;
 
    if (isspace(*ptr))
    {
      if (lastWasH==1) lastWasH=2;
      sprintf(out+strlen(out),"%c",*ptr);
      ptr+=1;
    }
    else if (strncmp(ptr,"\"",1)==0)
    {
      break;
    }
    else if (strncmp(ptr,":",1)==0)
    {
      if (lastWasH==1) lastWasH=2;
      sprintf(out+strlen(out),":");
      ptr+=1;
    }
    else if (strncmp(ptr,"/",1)==0)
    {
      sprintf(out+strlen(out),"/");
      ptr+=1;
    }
    else if (strncmp(ptr,"c",1)==0)
    {
      sprintf(out+strlen(out),"%ld/%ld/%02ld %ld:%02ld:%02ld",getMonth(),
        getMDay(),getYear()%100,getHour(),getMinute(),getSecond());
      ptr+=1;
    }
    else if (strncmp(ptr,"dddddd",6)==0)
    {
      sprintf(out+strlen(out),"%s %02ld, %ld",FULLMONTHS[getMonth()-1],
        getMDay(),getYear());
      ptr+=6;
    }
    else if (strncmp(ptr,"ddddd",5)==0)
    {
      sprintf(out+strlen(out),"%ld/%ld/%02ld",getMonth(),getMDay(),
        getYear()%100);
      ptr+=5;
    }
    /*else if (strncmp(ptr,"dddd",4)==0)
    {
      sprintf(out+strlen(out),"%s",FULLDAYS[getWDay()-1]);
      ptr+=4;
    }
    else if (strncmp(ptr,"ddd",3)==0)
    {
      sprintf(out+strlen(out),"%s",DAYS[getWDay()-1]);
      ptr+=3;
    }*/
    else if (strncmp(ptr,"dd",2)==0)
    {
      sprintf(out+strlen(out),"%02ld",getMDay());
      ptr+=2;
    }
    else if (strncmp(ptr,"d",1)==0)
    {
      sprintf(out+strlen(out),"%ld",getMDay());
      ptr+=1;
    }
    /*else if (strncmp(ptr,"ww",2)==0)
    {
      sprintf(out+strlen(out),"%02ld",getYWeek());
      ptr+=2;
    }*/
    /*else if (strncmp(ptr,"w",1)==0)
    {
      sprintf(out+strlen(out),"%ld",getWDay());
      ptr+=1;
    }*/
    else if (strncmp(ptr,"mmmm",4)==0)
    {
      sprintf(out+strlen(out),"%s",FULLMONTHS[getMonth()-1]);
      ptr+=4;
    }
    else if (strncmp(ptr,"mmm",3)==0)
    {
      sprintf(out+strlen(out),"%s",MONTHS[getMonth()-1]);
      ptr+=3;
    }
    else if (strncmp(ptr,"mm",2)==0)
    {
      if (lastWasH==1)
        sprintf(out+strlen(out),"%02ld",getMinute());
      else
        sprintf(out+strlen(out),"%02ld",getMonth());
      ptr+=2;
    }
    else if (strncmp(ptr,"m",1)==0)
    {
      if (lastWasH==1)
        sprintf(out+strlen(out),"%ld",getMinute());
      else
        sprintf(out+strlen(out),"%ld",getMonth());
      ptr+=1;
    }
    else if (strncmp(ptr,"q",1)==0)
    {
      sprintf(out+strlen(out),"%ld",((getMonth()-1)/4)+1);  // GetQuarter
      ptr+=1;
    }
    else if (strncmp(ptr,"yyyy",4)==0)
    {
      sprintf(out+strlen(out),"%ld",getYear());
      ptr+=4;
    }
    else if (strncmp(ptr,"yy",2)==0)
    {
      sprintf(out+strlen(out),"%02ld",getYear()%100);
      ptr+=2;
    }
    /*else if (strncmp(ptr,"y",1)==0)
    {
      sprintf(out+strlen(out),"%ld",getYDay());
      ptr+=1;
    }*/
    else if (strncmp(ptr,"hh",2)==0)
    {
      sprintf(out+strlen(out),"%02ld",getHour());
      lastWasH=2;  // needs to be 1 after top of loop decs it
      ptr+=2;
    }
    else if (strncmp(ptr,"h",1)==0)
    {
      sprintf(out+strlen(out),"%ld",getHour());
      lastWasH=2;  // needs to be 1 after top of loop decs it
      ptr+=1;
    }
    else if (strncmp(ptr,"nn",2)==0)
    {
      sprintf(out+strlen(out),"%02ld",getMinute());
      ptr+=2;
    }
    else if (strncmp(ptr,"n",1)==0)
    {
      sprintf(out+strlen(out),"%ld",getMinute());
      ptr+=1;
    }
    else if (strncmp(ptr,"ss",2)==0)
    {
      sprintf(out+strlen(out),"%02ld",getSecond());
      ptr+=2;
    }
    else if (strncmp(ptr,"s",1)==0)
    {
      sprintf(out+strlen(out),"%ld",getSecond());
      ptr+=1;
    }
    else if (strncmp(ptr,"ttttt",5)==0)
    {
      sprintf(out+strlen(out),"%ld:%02ld:%02ld",getHour(),getMinute(),
        getSecond());
      ptr+=5;
    }
    else if (strncmp(ptr,"aa",2)==0)
    {
      uint32 tmp = (getHour() <= 12) ? getHour() : getHour() - 12;
      sprintf(out+strlen(out),"%02ld", tmp);
      lastWasH=2;  // needs to be 1 after top of loop decs it
      ptr+=2;
      ampmflag = 1;
    }
   else  // an unknown char, move to next
     ptr++;
  }
  if(ampmflag)
  {
    char ampm[4];
    if( getHour() < 12 )
      strcpy(ampm, " AM");
    else
      strcpy(ampm, " PM");
    sprintf(out+strlen(out), "%s", ampm);
  }
  return(TRUE);
}
 
/**************************************

 REPLACE THIS CRAP

// Parses a date string that's in modified RFC 1123 format
// Can have a +minutes after the normal time
// eg: Thu, 20 Jun 1996 17:33:49 +100
// Returns true if successfully parsed, false otherwise
bit8 Xtime::ParseDate(char *in)
{
  int i;
  uint32 minOffset;
  struct tm t;
  char *ptr=in;
  while ((!isgraph(*ptr))&&(*ptr!=0)) ptr++;  // skip to start of string
  if (*ptr==0) return(FALSE);
  t.tm_wday_=-1;
  for (i=0; i<7; i++)  // parse day_ of week
    if (strncmp(ptr,DAYS[i],strlen(DAYS[i]))==0)
      t.tm_wday_=i;
  if (t.tm_wday_==-1)
    return(FALSE);
  while ((!isdigit(*ptr))&&(*ptr!=0)) ptr++;  // skip to day_ of month
  if (*ptr==0) return(FALSE);
  t.tm_mday_=atoi(ptr);
  while ((!isalpha(*ptr))&&(*ptr!=0)) ptr++;  // skip to month
  if (*ptr==0) return(FALSE);
  t.tm_mon=-1;
  for (i=0; i<12; i++)  // match month
    if (strncmp(ptr,MONTHS[i],strlen(MONTHS[i]))==0) t.tm_mon=i;
  if (t.tm_mon==-1) return(FALSE);
  while ((!isdigit(*ptr))&&(*ptr!=0)) ptr++;
  if (*ptr==0) return(FALSE);
  t.tm_year=atoi(ptr);
  if (t.tm_year<70)  // if they specify a 2 digit year, we'll be nice
    t.tm_year+=2000;
  else if (t.tm_year<100)
    t.tm_year+=1900;
  if (t.tm_year>2200)  // I doubt my code will be around for another 203 years
    return(FALSE);
  while ((isdigit(*ptr))&&(*ptr!=0)) ptr++;  // skip to end of year
  if (*ptr==0) return(FALSE);

  while ((!isgraph(*ptr))&&(*ptr!=0)) ptr++;  // skip to start of time
  if (*ptr==0) return(FALSE);

  t.tm_hour=atoi(ptr);
  while ((*ptr!=':')&&(*ptr!=0)) ptr++;
  ptr++; // skip past colon
  if (*ptr==0) return(FALSE);
  t.tm_min=atoi(ptr);
  while ((*ptr!=':')&&(*ptr!=0)) ptr++;
  ptr++; // skip past colon
  if (*ptr==0) return(FALSE);
  t.tm_sec=atoi(ptr);
  t.tm_year%=100;   // 1996 is stored as 96, not 1996
  t.tm_isdst=-1;    // day_light savings info isn't available

  sec=(uint32)(mktime(&t));
  if ((sint32)sec==-1)
    return(FALSE);


  // The next part of the time is OPTIONAL (+minutes)

  // first skip past the seconds 
  while ((isdigit(*ptr))&&(*ptr!=0)) ptr++;
  if (*ptr==0) return(TRUE);

  // skip past any spaces 
  while ((isspace(*ptr))&&(*ptr!=0)) ptr++;
  if (*ptr!='+')
  {
    //printf("\nNOPE ptr was '%s'\n",ptr);
    return(TRUE);
  }
  ptr++;
  if (*ptr==0)
  {
    //printf("\nPTR WAS 0\n");
    return(TRUE);
  }
 
  minOffset=atol(ptr);
  //printf("\n\nAdding %d minutes!\n\n",minOffset);
  sec+=minOffset*60;  // add the minutes as seconds
  return(TRUE);
}



// In addition to PrintTime & PrintDate there is the 'Print' function
//   which prints both in RFC 1123 format

void Xtime::PrintTime(FILE *out) const
{
  char string[80];
  PrintTime(string);
  fprintf(out,"%s",string);
}

void Xtime::PrintTime(char *out) const
{
  sprintf(out," %02lu:%02lu:%02lu",GetHour(),GetMinute(),GetSecond());
}

void Xtime::PrintDate(FILE *out) const
{
  char string[80];
  PrintDate(string);
  fprintf(out,"%s",string);
}

void Xtime::PrintDate(char *out) const
{
  sprintf(out,"%s, %lu %s %lu",DAYS[GetWDay()-1],GetMDay(),MONTHS[GetMonth()-1],
    GetYear());
}
********************************************/

// Get day_s since year 0
sint32 Xtime::getDay(void) const
{
  return(day_);
}

// Get msecs since start of day
sint32 Xtime::getMsec(void) const
{
  return(msec_);
}

// Set days since year 0
void Xtime::setDay(sint32 newday)
{
  day_=newday;
}

// Set msec since start of this day
void Xtime::setMsec(sint32 newmsec)
{
  msec_=newmsec;
}

// Set both
void Xtime::set(sint32 newday, sint32 newmsec)
{
  day_=newday;
  msec_=newmsec;
}


//
// Get a timeval ptr from a Xtime class
// May fail if timeval can't hold a year this big or small
//
bit8 Xtime::getTimeval(struct timeval &tv)
{
  // A timeval can only hold dates from 1970-2038
  if ((day_ < 719528) || (day_ >= 719528+24855))
    return(FALSE);

  // Compute seconds since Jan 1, 1970
  uint32 seconds=day_-719528;
  seconds*=(60*60*24);
  seconds+=(msec_/1000);

  tv.tv_sec=seconds;
  tv.tv_usec=(msec_%1000)*1000;
  return(TRUE);
}

//
// Set the time
//
bit8 Xtime::setTime(int month, int mday, int year, int hour, int minute, int second)
{
  day_=Get_Day(month,mday,year);
  msec_=(hour*1000*60*60)+(minute*1000*60)+(second*1000);
  return(TRUE);
}



int Xtime::getYDay(void) const   // Day of Year  (1-366)  (366 = leap yr)
{
	int year;
	sint32 dayofyear;
	if (Get_Date_From_Day(day_,year,dayofyear)==FALSE)
		return(-1);
	return dayofyear;
}


//
// Get all the components of the time in the usual normalized format.
//
// Most of the uglyness is in Get_Date_From_Day() 
//
bit8 Xtime::getTime(int &month, int &mday, int &year, int &hour, int &minute, int &second) const
{
  int i;
  sint32 dayofyear;
  if (Get_Date_From_Day(day_,year,dayofyear)==FALSE)
    return(FALSE);

  static int DaysAtMonth[2][12] = {
        {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},   // normal
        {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}    // leap year
  };

  month=0;

  bit8 isleap=IS_LEAP(year);
  for (i=0; i<12; i++)
  {
    if (DaysAtMonth[isleap][i] >= dayofyear)
      break;
    month=i;
  }
  month++;  // 1 based

  mday=dayofyear-DaysAtMonth[isleap][month-1];

  // Whew! Now all we have to do is figure out H/M/S from the msec!
  hour=(msec_/3600000)%24;  // 1000*60*60
  minute=(msec_/60000)%60;  // 1000*60 
  second=(msec_/ 1000)%60;  // 1000

  return(TRUE);
}

//
// These are for getting components of the time in the
//   standard ranges.  Like Day 1-31, Second 0-59, etc...
//
int Xtime::getSecond(void) const
{
  int month,mday,year,hour,minute,second;
  getTime(month, mday, year, hour, minute, second);
  return(second);
}
int Xtime::getMinute(void) const
{
  int month,mday,year,hour,minute,second;
  getTime(month, mday, year, hour, minute, second);
  return(minute);
}
int Xtime::getHour(void) const
{
  int month,mday,year,hour,minute,second;
  getTime(month, mday, year, hour, minute, second);
  return(hour);
}
int Xtime::getMDay(void) const
{
  int month,mday,year,hour,minute,second;
  getTime(month, mday, year, hour, minute, second);
  return(mday);
}

int Xtime::getMonth(void) const
{
  int month,mday,year,hour,minute,second;
  getTime(month, mday, year, hour, minute, second);
  return(month);
}

// based at year 0 (real 0, not 1970)
int Xtime::getYear(void) const
{
  int month,mday,year,hour,minute,second;
  getTime(month, mday, year, hour, minute, second);
  return(year);
}


//
// Set the seconds value (0-59)
//
bit8 Xtime::setSecond(sint32 sec)
{
  sint32 second=(msec_/ 1000)%60;
  msec_-=(second*1000);
  msec_+=(sec*1000);
  return(TRUE);
}

//
// Set the minutes value (0-59)
//
bit8 Xtime::setMinute(sint32 min)
{
  sint32 minute=(msec_/60000)%60;  // 1000*60 
  msec_-=(minute*60000);
  msec_+=(min*60000);
  return(TRUE);
}

//
// Set the minutes value (0-23)
//
bit8 Xtime::setHour(sint32 hour)
{
  hour=(msec_/3600000)%24;  // 1000*60*60
  msec_-=(hour*3600000);
  msec_+=(hour*3600000);
  return(TRUE);
}

//
// Set the year value
// Results are undefined if you're moving from Feb 29, to a non leap year
//
bit8 Xtime::setYear(sint32 _year)
{
  // extract the date
  int month,mday,year,hour,min,sec;
  getTime(month,mday,year,hour,min,sec);

  // modify & rebuild
  year=_year;
  day_=Get_Day(month,mday,year);
  return(TRUE);
}

//
// Modify the month
//
bit8 Xtime::setMonth(sint32 _month)
{
  // extract the date
  int month,mday,year,hour,min,sec;
  getTime(month,mday,year,hour,min,sec);

  // modify & rebuild
  month=_month;
  day_=Get_Day(month,mday,year);
  return(TRUE);
}


//
// Modify the day of the month 
//
bit8 Xtime::setMDay(sint32 _mday)
{
  // extract the date
  int month,mday,year,hour,min,sec;
  getTime(month,mday,year,hour,min,sec);

  // modify & rebuild
  mday=_mday;
  day_=Get_Day(month,mday,year);
  return(TRUE);
}


//
// Compare two times.  The time better be normalized
//   which it would be unless you've put bad stuff in it!
//
// 1 = *this > other
//-1 = *this < other
// 0 = *this == other
int   Xtime::compare(const Xtime &other) const
{
  if ((day_==other.day_)&&(msec_==other.msec_))
    return(0);        // equal

  else if (day_>other.day_)
    return(1);
  else if (day_<other.day_)
    return(-1);
  else if (msec_>other.msec_)
    return(1);
  else
    return(-1);
}
  

bit8 Xtime::operator == ( const Xtime &other ) const
{
  bit8 retval=compare(other);
  if (retval==0)
    return(TRUE);
  else
    return(FALSE);
}

bit8 Xtime::operator != ( const Xtime &other ) const
{
  bit8 retval=compare(other);
  if (retval==0)
    return(FALSE);
  else
    return(TRUE);
}

bit8 Xtime::operator < ( const Xtime &other ) const
{
  int retval=compare(other);
  if (retval==-1)
    return(TRUE);
  else
    return(FALSE);
}

bit8 Xtime::operator > ( const Xtime &other ) const
{
  int retval=compare(other);
  if (retval==1)
    return(TRUE);
  else
    return(FALSE);
}

bit8 Xtime::operator <= ( const Xtime &other ) const
{
  int retval=compare(other);
  if ((retval==-1)||(retval==0))
    return(TRUE);
  else
    return(FALSE);
}

bit8 Xtime::operator >= ( const Xtime &other ) const
{
  int retval=compare(other);
  if ((retval==1)||(retval==0))
    return(TRUE);
  else
    return(FALSE);
}


Xtime &Xtime::operator += (const Xtime &other)
{
  day_+=other.day_;
  msec_+=other.msec_;
  normalize();
  return *this;
}

Xtime &Xtime::operator -= (const Xtime &other)
{
  day_-=other.day_;
  msec_-=other.msec_;
  normalize();
  return *this;
}

Xtime Xtime::operator - (Xtime &other)
{
  Xtime temp(*this);
  temp-=other;
  return(temp);
}

Xtime Xtime::operator + (Xtime &other)
{
  Xtime temp(*this);
  temp+=other;
  return(temp);
}


Xtime   &Xtime::operator = (const Xtime &other)
{
  day_=other.day_;
  msec_=other.msec_;
  return *this;
}


Xtime &Xtime::operator += (const time_t other)
{
  addSeconds(other);
  return *this;
}


Xtime &Xtime::operator -= (const time_t other)
{
  addSeconds(-((sint32)other));
  return *this;
}


Xtime Xtime::operator - (time_t other)
{
  Xtime temp(*this);
  temp-=other;
  return(temp);
}


Xtime Xtime::operator + (time_t other)
{
  Xtime temp(*this);
  temp+=other;
  return(temp);
}

Xtime &Xtime::operator = (const time_t other)
{
  msec_=0;
  day_=719528;  // Jan 1, 1970
  addSeconds(other);
  return *this;
}
