⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dl_time.c

📁 This package contains the following source code files: - demo.c Demo application sourc
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************/
/*                                                                            */
/* Copyright (C) 2004-2007 Oscar Sanderson                                    */
/*                                                                            */
/* This software is provided 'as-is', without any express or implied          */
/* warranty.  In no event will the author(s) be held liable for any damages   */
/* arising from the use of this software.                                     */
/*                                                                            */
/* Permission is granted to anyone to use this software for any purpose,      */
/* including commercial applications, and to alter it and redistribute it     */
/* freely, subject to the following restrictions:                             */
/*                                                                            */
/* 1. The origin of this software must not be misrepresented; you must not    */
/*    claim that you wrote the original software. If you use this software    */
/*    in a product, an acknowledgment in the product documentation would be   */
/*    appreciated but is not required.                                        */
/*                                                                            */
/* 2. Altered source versions must be plainly marked as such, and must not be */
/*    misrepresented as being the original software.                          */
/*                                                                            */
/* 3. This notice may not be removed or altered from any source distribution. */
/*                                                                            */
/******************************************************************************/
/*                                                                            */
/* Date/Time module providing functionality for both UTC and Local values.    */
/* Uses a standard Epoch of 1/1/1970 00:00:00                                 */
/*                                                                            */
/* Provides full support if WIN32 is defined, otherwise defaults to GMT       */
/*                                                                            */
/******************************************************************************/

#include "dl_time.h"

/******************************************************************************/
//
// CONSTANTS
//

#define kMIN_YEAR				1970
#define kMAX_YEAR				2106

#define kTIMESTAMP_MIN_VALUE	"19700101000000"
#define kTIMESTAMP_MAX_VALUE	"21060207062815"

#define kSECONDS_IN_MINUTE		60
#define kMINUTES_IN_HOUR		60
#define kHOURS_IN_DAY			24
#define kDAYS_IN_NORMAL_YEAR	365

#define kSECONDS_IN_HOUR		(kMINUTES_IN_HOUR * kSECONDS_IN_MINUTE)
#define kSECONDS_IN_DAY			(kHOURS_IN_DAY * kSECONDS_IN_HOUR)
#define kSECONDS_IN_NORMAL_YEAR	(kDAYS_IN_NORMAL_YEAR * kSECONDS_IN_DAY)
#define kSECONDS_IN_LEAP_YEAR	(kSECONDS_IN_NORMAL_YEAR + kSECONDS_IN_DAY)

// indicates the day of week for 1/1/1970 (eg Thursday)
#define kFIRST_DAY_1970			kDL_TIME_DOW_THURSDAY

/******************************************************************************/
//
// TYPES
//

struct TZ_INFO_S
{
	/* seconds to be added to UTC to get 'base' localtime */
	DL_SINT32 baseBias;

	/* indicates if DST is used */
	int       hasDST; /* 0:No, else Yes */

	/* DST */
	DL_SINT32 dstBias;
	DL_TIME   dstStart;
	DL_TIME   dstEnd;
};
typedef struct TZ_INFO_S TZ_INFO;

/******************************************************************************/
//
// MACROS
//

/* indicates whether the specified year is a leap year */
#define isLeapYear(year)\
((year%4)?0:((year%100)?1:((year%400)?0:1)))

#define TZ_INFO_BASE_BIAS(tzInfo)	((tzInfo)->baseBias)
#define TZ_INFO_HAS_DST(tzInfo)		((tzInfo)->hasDST)
#define TZ_INFO_DST_BIAS(tzInfo)	((tzInfo)->dstBias)

/******************************************************************************/
//
// PRIVATE VARIABLES
//

static int     _haveTZ = 0;
static TZ_INFO _tz;

/******************************************************************************/

// NB only loads time-zone details on the first execution
static void _get_tz_info ( void );

/******************************************************************************/

static void DL_TIME_Populate ( int      iYear,
							   int      iMonth,
							   int      iDay,
							   int      iHour,
							   int      iMinute,
							   int      iSecond,
							   int      _iDayOfWeek,
							   DL_TIME *oData );

/******************************************************************************/

static void seconds_to_struct ( DL_UINT32  iSeconds,
							    DL_TIME   *oData );

/******************************************************************************/

/* NB '_year' should be specified if 'day-in-month' mode used */
static void struct_to_timestamp ( int            _iYear,
								  const DL_TIME *iData,
								  char          *oTimestampStr );

/******************************************************************************/

/* NB '_year' should be specified if 'day-in-month' mode used */
static void struct_to_seconds ( int            _iYear,
							    const DL_TIME *iData,
							    DL_UINT32     *oSeconds );

/* converts a timestamp (YYYYMMDDHHMISS) to the date/time structure */
/* returns: 1 if ok / 0 otherwise (eg invalid timestamp)            */
static int timestamp_to_struct ( const char *iTimestampStr,
								 DL_TIME    *oData );

/******************************************************************************/

// ensures that any 'Day-in-Month' values are converted to absolute
static void rationalise_struct ( int            _iYear,
								 const DL_TIME *iData,
								 DL_TIME       *oData );

static int calc_day_of_week ( int iYear,
							  int iMonth,
							  int iDay );

static int calc_days_in_month ( int iYear,
							    int iMonth );

static void calc_dst_start_end ( int        _iYear,
								 DL_UINT32 *iDstStart,
								 DL_UINT32 *iDstEnd );

/******************************************************************************/

DL_UINT32 DL_TIME_GetUTCSeconds ( void )
{
	DL_UINT32 ret = 0;

	ret = (DL_UINT32)(time(NULL) & DL_MAX_UINT32);

	return ret;
}

/******************************************************************************/

void DL_TIME_ConvUTCSecondsToLocalStruct ( DL_UINT32  iUtcSecs,
										   DL_TIME   *oData )
{
	/* get time-zone specific settings */
	_get_tz_info();

	/* apply base Bias to UTC value */
	iUtcSecs += TZ_INFO_BASE_BIAS(&_tz);

	/* convert seconds to struct */
	seconds_to_struct(iUtcSecs,oData);

	/* perform Std/DST adjustment (where required) */
	if ( TZ_INFO_HAS_DST(&_tz) )
	{
		int       inDST    = 0;
		DL_UINT32 dstStart = 0,
		          dstEnd   = 0;

		calc_dst_start_end(oData->year,&dstStart,&dstEnd);

		if ( ((dstStart <= dstEnd) &&  (iUtcSecs >= dstStart) && (iUtcSecs < dstEnd))  ||
		     ((dstStart >  dstEnd) && ((iUtcSecs >= dstStart) || (iUtcSecs < dstEnd))) )
		{
			inDST = 1;
		}

		if ( inDST )
		{
			/* apply DST bias */
			iUtcSecs += TZ_INFO_DST_BIAS(&_tz);
		}

		/* convert seconds to struct */
		seconds_to_struct(iUtcSecs,oData);
	}

	return;
}

/******************************************************************************/

void DL_TIME_ConvUTCSecondsToLocalTimestamp ( DL_UINT32 iUtcSecs,
											  char      oTimestamp[] )
{
	DL_TIME st;

	/* convert seconds (utc) to struct (local) */
	DL_TIME_ConvUTCSecondsToLocalStruct(iUtcSecs,&st);

	/* convert struct to timestamp */
	struct_to_timestamp(0,&st,oTimestamp);

	return;
}

/******************************************************************************/

void DL_TIME_ConvUTCSecondsToUTCStruct ( DL_UINT32  iUtcSecs,
										 DL_TIME   *oData )
{
	/* convert seconds to struct */
	seconds_to_struct(iUtcSecs,oData);

	return;
}

/******************************************************************************/

void DL_TIME_ConvUTCSecondsToUTCTimestamp ( DL_UINT32 iUtcSecs,
										    char      oTimestamp[] )
{
	DL_TIME st;

	/* convert seconds (utc) to struct (utc) */
	DL_TIME_ConvUTCSecondsToUTCStruct(iUtcSecs,&st);

	/* convert struct to timestamp */
	struct_to_timestamp(0,&st,oTimestamp);

	return;
}

/******************************************************************************/

int DL_TIME_ConvUTCTimestampToUTCSeconds ( const char  iTimestamp[],
										   DL_UINT32  *oUtcSecs )
{
	int     ok = 1;
	DL_TIME st;

	/* init outputs */
	*oUtcSecs = 0;

	/* timestamp (utc) to struct (utc) */
	ok = timestamp_to_struct(iTimestamp,&st);

	if ( ok )
	{
		/* struct (utc) to seconds (utc) */
		struct_to_seconds(0,&st,oUtcSecs);
	}

	return ok;
}

/******************************************************************************/

int DL_TIME_ConvLocalTimestampToUTCSeconds ( const char  iTimestamp[],
											 DL_UINT32  *oUtcSecs )
{
	int     ok = 1;
	DL_TIME st;

	/* init outputs */
	*oUtcSecs = 0;

	/* get time-zone specific settings */
	_get_tz_info();

	/* timestamp (local) to struct (local) */
	ok = timestamp_to_struct(iTimestamp,&st);

	if ( ok )
	{
		/* struct (local) to seconds (local) */
		struct_to_seconds(0,&st,oUtcSecs);

		/* perform Std/DST adjustment (where required) */
		if ( TZ_INFO_HAS_DST(&_tz) )
		{
			int       inDST    = 0;
			DL_UINT32 dstStart = 0,
				      dstEnd   = 0;

			calc_dst_start_end(st.year,&dstStart,&dstEnd);

			dstStart += TZ_INFO_DST_BIAS(&_tz);
			dstEnd   -= TZ_INFO_DST_BIAS(&_tz);

			if ( ((dstStart <= dstEnd) &&  (*oUtcSecs >= dstStart) && (*oUtcSecs < dstEnd))  ||
			     ((dstStart >  dstEnd) && ((*oUtcSecs >= dstStart) || (*oUtcSecs < dstEnd))) )
			{
				inDST = 1;
			}

			if ( inDST )
			{
				/* remove DST bias */
				*oUtcSecs -= TZ_INFO_DST_BIAS(&_tz);
			}
		}

		/* remove base Bias to UTC value */
		*oUtcSecs -= TZ_INFO_BASE_BIAS(&_tz);
	}

	return ok;
}

/******************************************************************************/

void DL_TIME_ConvUTCSecondsToLocalFormatStr ( DL_UINT32  iUtcSecs,
										      char      *ioFormatStr )
{
	DL_TIME st;

	/* init outputs */
	sprintf(ioFormatStr,"");

	/* convert UTC seconds to Local structure */
	DL_TIME_ConvUTCSecondsToLocalStruct(iUtcSecs,&st);

	/* populate buffer */
	sprintf(ioFormatStr,"%02d/%02d/%04d (%02d:%02d:%02d)",
			st.day,
			st.month,
			st.year,
			st.hour,
			st.minute,
			st.second);

	return;
}

/******************************************************************************/

int _DL_TIME_AddMonths ( DL_UINT32  iSeconds,
						 DL_UINT16  iNumMonths,
						 DL_UINT32 *oSeconds )
{
	int     ok = 1;
	DL_TIME dt;

	/* convert to nice date/time format */
	DL_TIME_ConvUTCSecondsToUTCStruct(iSeconds,&dt);

	if ( ok )
	{
		int years  = iNumMonths / 12;
		int months = iNumMonths % 12;

		/* add whole years */
		dt.year += years;

		/* add partial months (may cause year overflow) */
		if ( (dt.month + months) <= 12 ) /* same year */
		{
			dt.month += months;
		}
		else /* next year */
		{
			dt.year++;
			dt.month = (dt.month + months) - 12;
		}

		/* adjust 'day' if exceeds maximum for month/year combination */
		dt.day = MAX(dt.day,calc_days_in_month(dt.year,dt.month));
	}

	/* convert back to seconds and pass to caller */
	if ( ok )
	{
		/* struct (utc) to seconds (utc) */
		struct_to_seconds(0,&dt,oSeconds);
	}

	/* check for seconds overflow */
	if ( ok && (iSeconds > *oSeconds) )
	{
		/* overflow because input is greater than output */
		ok = 0;
	}

	return ok;
}

/******************************************************************************/

void _DL_TIME_GetDaysInMonth ( int  iMonth,
						       int  iYear,
							   int *oDaysInMonth )
{
	/* init outputs */
	*oDaysInMonth     = 0;

	/* determine 'days in month' */
	*oDaysInMonth = calc_days_in_month(iYear,iMonth);

	return;
}

/******************************************************************************/

static void _get_tz_info ( void )
{
	/* do nothing if we have already loaded the time zone details */
	if ( _haveTZ )
		return;

	/* init structure */
	DL_MEM_memset(&_tz,0,sizeof(TZ_INFO));

#if defined(DL_WIN32)
	{
		TIME_ZONE_INFORMATION winTZ;
		DWORD                 rc;
		int                   tempOk = 1;

		/* get timezone */
		rc = GetTimeZoneInformation(&winTZ);

		if ( rc == TIME_ZONE_ID_UNKNOWN )
		{
			/* timezone does NOT have DST */
			_tz.hasDST = 0;
		}
		else if ( (rc == TIME_ZONE_ID_STANDARD) ||

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -