mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-06-01 14:22:41 -06:00
153 lines
5.4 KiB
C++
153 lines
5.4 KiB
C++
/**********************************************************************
|
|
* $Id: cpl_time.cpp 18063 2009-11-21 21:11:49Z warmerdam $
|
|
*
|
|
* Name: cpl_time.cpp
|
|
* Project: CPL - Common Portability Library
|
|
* Purpose: Time functions.
|
|
* Author: Even Rouault, <even dot rouault at mines dash paris dot org>
|
|
*
|
|
**********************************************************************
|
|
*
|
|
* CPLUnixTimeToYMDHMS() is derived from timesub() in localtime.c from openbsd/freebsd/netbsd.
|
|
* CPLYMDHMSToUnixTime() has been implemented by Even Rouault and is in the public domain
|
|
*
|
|
* Cf http://svn.freebsd.org/viewvc/base/stable/7/lib/libc/stdtime/localtime.c?revision=178142&view=markup
|
|
* localtime.c comes with the following header :
|
|
*
|
|
* This file is in the public domain, so clarified as of
|
|
* 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
|
|
*/
|
|
|
|
#include "cpl_time.h"
|
|
|
|
#define SECSPERMIN 60L
|
|
#define MINSPERHOUR 60L
|
|
#define HOURSPERDAY 24L
|
|
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
|
|
#define SECSPERDAY (SECSPERHOUR * HOURSPERDAY)
|
|
#define DAYSPERWEEK 7
|
|
#define MONSPERYEAR 12
|
|
|
|
#define EPOCH_YEAR 1970
|
|
#define EPOCH_WDAY 4
|
|
#define TM_YEAR_BASE 1900
|
|
#define DAYSPERNYEAR 365
|
|
#define DAYSPERLYEAR 366
|
|
|
|
#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
|
|
#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
|
|
|
|
static const int mon_lengths[2][MONSPERYEAR] = {
|
|
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
|
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
|
|
} ;
|
|
|
|
|
|
static const int year_lengths[2] = {
|
|
DAYSPERNYEAR, DAYSPERLYEAR
|
|
};
|
|
|
|
/************************************************************************/
|
|
/* CPLUnixTimeToYMDHMS() */
|
|
/************************************************************************/
|
|
|
|
/** Converts a time value since the Epoch (aka "unix" time) to a broken-down UTC time.
|
|
*
|
|
* This function is similar to gmtime_r().
|
|
* This function will always set tm_isdst to 0.
|
|
*
|
|
* @param unixTime number of seconds since the Epoch.
|
|
* @param pRet address of the return structure.
|
|
*
|
|
* @return the structure pointed by pRet filled with a broken-down UTC time.
|
|
*/
|
|
|
|
struct tm * CPLUnixTimeToYMDHMS(GIntBig unixTime, struct tm* pRet)
|
|
{
|
|
GIntBig days = unixTime / SECSPERDAY;
|
|
GIntBig rem = unixTime % SECSPERDAY;
|
|
|
|
while (rem < 0) {
|
|
rem += SECSPERDAY;
|
|
--days;
|
|
}
|
|
|
|
pRet->tm_hour = (int) (rem / SECSPERHOUR);
|
|
rem = rem % SECSPERHOUR;
|
|
pRet->tm_min = (int) (rem / SECSPERMIN);
|
|
/*
|
|
** A positive leap second requires a special
|
|
** representation. This uses "... ??:59:60" et seq.
|
|
*/
|
|
pRet->tm_sec = (int) (rem % SECSPERMIN);
|
|
pRet->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
|
|
if (pRet->tm_wday < 0)
|
|
pRet->tm_wday += DAYSPERWEEK;
|
|
GIntBig y = EPOCH_YEAR;
|
|
int yleap;
|
|
while (days < 0 || days >= (GIntBig) year_lengths[yleap = isleap(y)])
|
|
{
|
|
GIntBig newy;
|
|
|
|
newy = y + days / DAYSPERNYEAR;
|
|
if (days < 0)
|
|
--newy;
|
|
days -= (newy - y) * DAYSPERNYEAR +
|
|
LEAPS_THRU_END_OF(newy - 1) -
|
|
LEAPS_THRU_END_OF(y - 1);
|
|
y = newy;
|
|
}
|
|
pRet->tm_year = (int) (y - TM_YEAR_BASE);
|
|
pRet->tm_yday = (int) days;
|
|
const int* ip = mon_lengths[yleap];
|
|
for (pRet->tm_mon = 0; days >= (GIntBig) ip[pRet->tm_mon]; ++(pRet->tm_mon))
|
|
days = days - (GIntBig) ip[pRet->tm_mon];
|
|
pRet->tm_mday = (int) (days + 1);
|
|
pRet->tm_isdst = 0;
|
|
|
|
return pRet;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* CPLYMDHMSToUnixTime() */
|
|
/************************************************************************/
|
|
|
|
/** Converts a broken-down UTC time into time since the Epoch (aka "unix" time).
|
|
*
|
|
* This function is similar to mktime(), but the passed structure is not modified.
|
|
* This function ignores the tm_wday, tm_yday and tm_isdst fields of the passed value.
|
|
* No timezone shift will be applied. This function returns 0 for the 1/1/1970 00:00:00
|
|
*
|
|
* @param brokendowntime broken-downtime UTC time.
|
|
*
|
|
* @return a number of seconds since the Epoch encoded as a value of type GIntBig,
|
|
* or -1 if the time cannot be represented.
|
|
*/
|
|
|
|
GIntBig CPLYMDHMSToUnixTime(const struct tm *brokendowntime)
|
|
{
|
|
GIntBig days;
|
|
int mon;
|
|
|
|
if (brokendowntime->tm_mon < 0 || brokendowntime->tm_mon >= 12)
|
|
return -1;
|
|
|
|
/* Number of days of the current month */
|
|
days = brokendowntime->tm_mday - 1;
|
|
|
|
/* Add the number of days of the current year */
|
|
const int* ip = mon_lengths[isleap(TM_YEAR_BASE + brokendowntime->tm_year)];
|
|
for(mon=0;mon<brokendowntime->tm_mon;mon++)
|
|
days += ip [mon];
|
|
|
|
/* Add the number of days of the other years */
|
|
days += (TM_YEAR_BASE + (GIntBig)brokendowntime->tm_year - EPOCH_YEAR) * DAYSPERNYEAR +
|
|
LEAPS_THRU_END_OF(TM_YEAR_BASE + (GIntBig)brokendowntime->tm_year - 1) -
|
|
LEAPS_THRU_END_OF(EPOCH_YEAR - 1);
|
|
|
|
/* Now add the secondes, minutes and hours to the number of days since EPOCH */
|
|
return brokendowntime->tm_sec +
|
|
brokendowntime->tm_min * SECSPERMIN +
|
|
brokendowntime->tm_hour * SECSPERHOUR +
|
|
days * SECSPERDAY;
|
|
}
|