/**********************************************************************
 *
 * gsdltimes.cpp -- functions to deal with time
 * Copyright (C) 1999  DigiLib Systems Limited, New Zealand
 *
 * A component of the Greenstone digital library software
 * from the New Zealand Digital Library Project at the
 * University of Waikato, New Zealand.
 *
 * 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 2 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, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *********************************************************************/

#include "gsdltimes.h"

// returns a string of the form "YYYY/MM/DD hh:mm:ss" (expressed in
// Coordinated Universal Time (UTC))
// returns "" if an error occurs
// !! Actually, we now return a string in localtime, as text2time returns
//    a time in localtime (mktime assumes local timezone). - jrm21 Sep 2002
text_t time2text (time_t time) {
  // tm *tm_ptr = gmtime(&time);
  tm *tm_ptr = localtime(&time);

  if (tm_ptr == NULL) return g_EmptyText;

  // year
  text_t timestr(tm_ptr->tm_year+1900);
  timestr.push_back('/');

  // month (note the +1)
  if ((tm_ptr->tm_mon+1) < 10) timestr.push_back('0');
  timestr += (tm_ptr->tm_mon+1);
  timestr.push_back('/');

  // day
  if (tm_ptr->tm_mday < 10) timestr.push_back('0');
  timestr += tm_ptr->tm_mday;
  timestr.push_back(' ');

  // hour
  if (tm_ptr->tm_hour < 10) timestr.push_back('0');
  timestr += tm_ptr->tm_hour;
  timestr.push_back(':');

  // minutes
  if (tm_ptr->tm_min < 10) timestr.push_back('0');
  timestr += tm_ptr->tm_min;
  timestr.push_back(':');

  // seconds
  if (tm_ptr->tm_sec < 10) timestr.push_back('0');
  timestr += tm_ptr->tm_sec;

  return timestr;
}

// takes a string like that returned by time2text and returns corresponding time_t
// returns -1 if an error occurs
time_t text2time (const text_t &timestr) {
  tm timetm;
  text_t tempstr;
  
  text_t::const_iterator time_here = timestr.begin();
  text_t::const_iterator time_end = timestr.end();

  // year
  if (time_here == time_end) return (time_t) -1;
  time_here = getdelimitstr (time_here, time_end, '/', tempstr);
  timetm.tm_year = tempstr.getint() - 1900;
  if (timetm.tm_year < 0) return (time_t) -1;

  // month (note the -1)
  if (time_here == time_end) return (time_t) -1;
  time_here = getdelimitstr (time_here, time_end, '/', tempstr);
  timetm.tm_mon = tempstr.getint() - 1;
  if (timetm.tm_mon < 0 || timetm.tm_mon > 11)
    return (time_t) -1;
  
  // day
  if (time_here == time_end) return (time_t) -1;
  time_here = getdelimitstr (time_here, time_end, ' ', tempstr);
  timetm.tm_mday = tempstr.getint();
  if (timetm.tm_mday < 1 || timetm.tm_mday > 31)
    return (time_t) -1;
  
  // hour
  if (time_here == time_end) return (time_t) -1;
  time_here = getdelimitstr (time_here, time_end, ':', tempstr);
  timetm.tm_hour = tempstr.getint();
  if (timetm.tm_hour < 0 || timetm.tm_hour > 23)
    return (time_t) -1;
  
  // min
  if (time_here == time_end) return (time_t) -1;
  time_here = getdelimitstr (time_here, time_end, ':', tempstr);
  timetm.tm_min = tempstr.getint();
  if (timetm.tm_min < 0 || timetm.tm_min > 59)
    return (time_t) -1;
  
  // sec
  if (time_here == time_end) return (time_t) -1;
  time_here = getdelimitstr (time_here, time_end, ':', tempstr);
  timetm.tm_sec = tempstr.getint();
  if (timetm.tm_sec < 0 || timetm.tm_sec > 59)
    return (time_t) -1;

  timetm.tm_isdst=0;

  /* This is for darwin - mktime seems to use this, so don't leave it
     uninitialised!! Maybe the same on freebsd/netbsd?
  */
#if defined(__MACH__) && defined(__APPLE__)
  timetm.tm_gmtoff=0;
#endif

  // mktime assumes timetm is localtime
  return mktime (&timetm);
}

// returns current date and time formatted like "Thu Dec 07 23:43:38 GMT 2000"
// if ltime is true return value will be expressed in local time, otherwise
// it'll be Coordinated Universal Time (UTC) - no promises are made that the
// resulting string will be formatted exactly as expected, especially on windows
// returns "" if an error occurs
text_t get_date (bool ltime) {

  tm *tm_ptr = NULL;
  time_t t = time(NULL);
  if (ltime) tm_ptr = localtime (&t);
  else tm_ptr = gmtime (&t);
  if (tm_ptr == NULL) return g_EmptyText;
  char *timestr = new char[128];
  text_t ret;

  // we do this in such an ugly way because windows is kind of flakey when
  // it comes to timezones
  if (ltime) {
    strftime (timestr, 128, "%a %b %d %H:%M:%S %z %Y", tm_ptr);
    ret.setcstr (timestr);
  } else {
    strftime (timestr, 128, "%a %b %d %H:%M:%S", tm_ptr);
    ret.setcstr (timestr);
    ret += " GMT ";
    strftime (timestr, 128, "%Y", tm_ptr);
    ret += timestr;
  }

  delete []timestr;
  return ret;
}
