/**************************************************************************
*** COPYRIGHT (c) 2002 by TransNexus, Inc. ***
*** ***
*** This software is property of TransNexus, Inc. ***
*** This software is freely available under license from TransNexus. ***
*** The license terms and conditions for free use of this software by ***
*** third parties are defined in the OSP Toolkit Software License ***
*** Agreement (LICENSE.txt). Any use of this software by third ***
*** parties, which does not comply with the terms and conditions of the ***
*** OSP Toolkit Software License Agreement is prohibited without ***
*** the prior, express, written consent of TransNexus, Inc. ***
*** ***
*** Thank you for using the OSP ToolKit(TM). Please report any bugs, ***
*** suggestions or feedback to support@transnexus.com ***
*** ***
**************************************************************************/
/*
* ospostime.c - OS-specific time functions
*/
#include "assert.h"
#include "time.h"
#ifndef _WIN32
#include <sys/timeb.h>
#else
#include <sys\timeb.h>
#endif
#ifndef _WIN32
#include "sys/time.h"
#include "unistd.h"
#endif
#include "osp/osp.h"
#include "osp/ospostime.h"
OSPTTIME OSPPOSTimeConvertToGMT(int, int, int, int, int, int);
/* A leap year is defined as 1) multiple of 4; 2) Not a multiple */
/* of 100, unless 3) it's a multiple of 400 */
#define OSPM_IS_LEAP(y) ((y) % 4) == 0 && (! ((y) % 100) == 0 || ((y) % 400) == 0)
/**/
/*-----------------------------------------------------------------------*
* OSPPOSTimeConvertToGMT() - convert calendar time to display string
*-----------------------------------------------------------------------*/
OSPTTIME
OSPPOSTimeConvertToGMT(
int month, /* Month (1-12!) */
int day, /* Day of month */
int year, /* Year (minus 1900) */
int hour, /* Hour */
int minute, /* Minute */
int second) /* Second */
{
OSPTTIME 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. */
year+=1900;
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) && OSPM_IS_LEAP(year))
{
--days;
}
days -= 719528; /* Subtract out Jan 1, 1970 base date */
return((days * 86400) + (hour * 3600) + (minute * 60) + second);
}
/**/
/*-----------------------------------------------------------------------*
* OSPPOSTimeCalToString() - convert calendar time to display string
*-----------------------------------------------------------------------*/
unsigned /* returns error code (0 if no error) */
OSPPOSTimeCalToString(
OSPTTIME ospvCalTime, /* calendar time (in UTC) */
char *ospvTimeString /* where to put time string */
)
{
#ifndef _WIN32
struct tm t;
#else
struct tm *t;
#endif
unsigned ospvErrCode = OSPC_ERR_NO_ERROR;
size_t chars;
/*
* This is all pretty much ANSI C standard - but be sure to use
* thread-safe versions.
*/
/*
* Convert to struct tm, preserving UTC (the ignored return is just
* a pointer to the struct tm).
*/
#ifndef _WIN32
(void)gmtime_r(&ospvCalTime, &t);
#else
t = gmtime(&ospvCalTime);
#endif
#ifndef _WIN32
/* format the output string */
chars = strftime(ospvTimeString, OSPC_TIMESTRINGSIZE,
"%Y-%m-%dT%H:%M:%SZ", &t);
#else
/* format the output string */
chars = strftime(ospvTimeString, OSPC_TIMESTRINGSIZE,
"%Y-%m-%dT%H:%M:%SZ", t);
#endif
/* make sure the strftime() call was okay */
if (chars == OSPC_TIMESTRINGSIZE)
{
ospvErrCode = (unsigned)OSPC_ERR_OS_FAILURE;
}
else
{
ospvErrCode = OSPC_ERR_NO_ERROR;
}
return(ospvErrCode);
}
/**/
/*-----------------------------------------------------------------------*
* OSPPOSTimeStringToCal() - convert display string to calendar time
*-----------------------------------------------------------------------*/
unsigned /* returns error code (0 if no error) */
OSPPOSTimeStringToCal(
const char *ospvTimeString, /* time string */
OSPTTIME *ospvCalTime /* where to put calendar time */
)
{
unsigned ospvErrCode = OSPC_ERR_NO_ERROR;
int year, month, day, hour, minute, second;
/*
* Unfortunately, this function is somewhat of a pain. The real
* problem is daylight savings time. The only standard way to
* generate a calendar time value is with the function mktime(),
* and that function takes a struct tm input, which is in local
* time (e.g. with time zone and daylight savings time accounted
* for). So, even though we're starting with UTC and ending
* with UTC, the intermediate step requires local time.
*/
/* build up a struct tm from the string */
/* OSP string time format is YYYY-MM-DDThh:mm:ssZ */
year = (ospvTimeString[0] - '0')*1000 + (ospvTimeString[1] - '0')*100 +
(ospvTimeString[2] - '0')*10 + (ospvTimeString[3] - '0');
month = (ospvTimeString[5] - '0')*10 + (ospvTimeString[6] - '0') - 1;
day = (ospvTimeString[8] - '0')*10 + (ospvTimeString[9] - '0');
hour = (ospvTimeString[11] - '0')*10 + (ospvTimeString[12] - '0');
minute = (ospvTimeString[14] - '0')*10 + (ospvTimeString[15] - '0');
second = (ospvTimeString[17] - '0')*10 + (ospvTimeString[18] - '0');
*ospvCalTime=OSPPOSTimeConvertToGMT(month+1,day,year-1900,hour,minute,second);
ospvErrCode=OSPC_ERR_NO_ERROR;
return(ospvErrCode);
}
int
OSPPOSTimeGetTime(
OSPTTIME *ospvTime,
unsigned int *ospvMilliseconds)
{
int errorcode = OSPC_ERR_NO_ERROR;
if ((ospvTime == OSPC_OSNULL) && (ospvMilliseconds == OSPC_OSNULL))
{
errorcode = OSPC_ERR_INVALID_POINTER;
OSPM_DBGERRORLOG(errorcode,
"Null pointers specified for time and mstime");
}
else
{
#ifndef _WIN32 /* UNIX */
struct timeb timenow;
OSPM_MEMSET(&timenow, 0, sizeof(struct timeb));
errorcode = ftime(&timenow);
#else
struct _timeb timenow;
OSPM_MEMSET(&timenow, 0, sizeof(struct _timeb));
_ftime(&timenow);
#endif
if (errorcode == OSPC_ERR_NO_ERROR)
{
if (ospvTime != OSPC_OSNULL)
{
*ospvTime = timenow.time;
}
if (ospvMilliseconds != OSPC_OSNULL)
{
*ospvMilliseconds = timenow.millitm;
}
}
else
{
errorcode = OSPC_ERR_TIME_ERROR;
OSPM_DBGERRORLOG(errorcode, "ftime reported an error");
}
}
return errorcode;
}
int
OSPPOSTimeFormatGMTTime(
OSPTTIME ospvTime,
char *ospvFormat,
char *ospvTimeString)
{
int errorcode = OSPC_ERR_NO_ERROR;
int chars = 0;
/* Converts a time in seconds since the BASETIME and then formats time
according to the format string. ospvTimeString be provided by the
caller and must be at least OSPC_TIMESTRINGSIZE characters */
#ifndef _WIN32
struct tm t;
OSPM_MEMSET( &t, 0, sizeof(struct tm));
#else
struct tm *t;
#endif
if ((ospvFormat == OSPC_OSNULL) || (ospvTimeString == OSPC_OSNULL))
{
errorcode = OSPC_ERR_INVALID_POINTER;
OSPM_DBGERRORLOG(errorcode,
"Invalid pointer to format or output string");
}
if (errorcode == OSPC_ERR_NO_ERROR)
{
#ifndef _WIN32
(void)gmtime_r(&ospvTime, &t);
#else
t = gmtime(&ospvTime);
#endif
#ifndef _WIN32
/* format the output string */
chars = strftime(ospvTimeString, OSPC_TIMESTRINGSIZE,
ospvFormat, &t);
#else
/* format the output string */
chars = strftime(ospvTimeString, OSPC_TIMESTRINGSIZE,
ospvFormat, t);
#endif
if (chars == 0)
{
errorcode = OSPC_ERR_TIME_ERROR;
OSPM_DBGERRORLOG(errorcode, "error occurred formatting time");
}
}
return errorcode;
}