关于网络校时时间转换的算法

Nio96 2009-08-17 10:59:02
当前我正在写一个网络校时的小应用,在网上看了一下别人写的代码,有一段算法不是很懂.请各位大侠帮忙解释一下,谢谢.

如下:
其中ulTime是从校时服务器发过来的从1900年1月1日到现在已经经过的秒数,有两个问题:
1。根据返回来的时间,我觉得服务器已经把时区考虑在内了,可能是根据发起连接的IP判断你当前所在的时区,再把相应的秒数发回来的,但是没有找到确定的依据。
2。这里有一段的算法不是很明白他为什么要这么写,哪位大侠不吝指点一下,谢谢。
SystemTimeToFileTime(&st, &ft);
li = *(LARGE_INTEGER*)&ft;
li.QuadPart += (LONGLONG)10000000 * ulTime;
ft = *(FILETIME*)&li;
FileTimeToSystemTime(&ft, &st);
SetSystemTime(&st);


LOCAL void MySetTime(uint32 ulTime)
{
FILETIME ft;
SYSTEMTIME st;
LARGE_INTEGER li;

st.wYear = 1900;
st.wMonth = 1;
st.wDay = 1;
st.wHour = 0;
st.wMinute = 0;
st.wSecond = 0;
st.wMilliseconds = 0;

SystemTimeToFileTime(&st, &ft);
li = *(LARGE_INTEGER*)&ft;
li.QuadPart += (LONGLONG)10000000 * ulTime;
ft = *(FILETIME*)&li;
FileTimeToSystemTime(&ft, &st);
SetSystemTime(&st);
}
...全文
789 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
goodname 2009-08-20
  • 打赏
  • 举报
回复
vc6安装的时候是可以选择的。
Nio96 2009-08-20
  • 打赏
  • 举报
回复
好了.可以结贴了.

不知道是否有地方可以下到lib库的源码呢? 我下了个LINUX KERNEL,里面也没有相关函数的源码.

VC 里面的源码不全的.
Nio96 2009-08-19
  • 打赏
  • 举报
回复
谢谢知秋,我的没有安装源代码,不知道是不是有办法可以安上?我用的是VS 6, 硬盘安装的.
goodname 2009-08-19
  • 打赏
  • 举报
回复

/***
*struct tm *__getgmtimebuf() - get the static/allocated buffer used by gmtime
*
*Purpose:
* get the buffer used by gmtime
*
*Entry:
*
*Exit:
* returns pointer to tm structure or NULL when allocation fails
*
*Exceptions:
*
*******************************************************************************/
struct tm * __cdecl __getgmtimebuf ()
{

REG2 struct tm *ptb; /* will point to gmtime buffer */
_ptiddata ptd = _getptd_noexit();
if (!ptd) {
errno = ENOMEM;
return (NULL);
}

/* Use per thread buffer area (malloc space, if necessary) */

if ( (ptd->_gmtimebuf != NULL) || ((ptd->_gmtimebuf =
_malloc_crt(sizeof(struct tm))) != NULL) )
ptb = ptd->_gmtimebuf;
else
{
errno = ENOMEM;
}
return ptb;
}
goodname 2009-08-19
  • 打赏
  • 举报
回复
装了vs开发环境一般同时安装了源代码,调试的时候应该可以跟进去。

以下是vs2005下的部分代码

_CRT_INSECURE_DEPRECATE(localtime_s) static __inline struct tm * __CRTDECL localtime(const time_t * _Time)
{
#pragma warning( push )
#pragma warning( disable : 4996 )
return _localtime64(_Time);
#pragma warning( pop )
}
/***
*loctim64.c - Convert __time64_t value to time structure
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Converts time stored as a __time64_t value to a structure of type
* struct tm expressed as local time.
*
*******************************************************************************/

#include <cruntime.h>
#include <limits.h>
#include <time.h>
#include <stddef.h>
#include <memory.h>
#include <ctime.h>
#include <internal.h>


/***
*struct tm *_localtime64_s(ptm, ptime) - convert __time64_t value to tm structure
*
*Purpose:
* Convert a value in 64-bit internal (__time64_t) format to a tm struct
* containing the corresponding local time.
*
* NOTES:
* (1) gmtime must be called before _isindst to ensure that the tb time
* structure is initialized.
* (2) gmtime, _gtime64, localtime and _localtime64() all use a single
* statically allocated buffer. Each call to one of these routines
* destroys the contents of the previous call.
* (3) It is assumed that __time64_t is a 64-bit integer representing
* the number of seconds since 00:00:00, 01-01-70 (UTC) (i.e., the
* Posix/Unix Epoch. Only non-negative values are supported.
* (4) It is assumed that the maximum adjustment for local time is
* less than three days (include Daylight Savings Time adjustment).
* This only a concern in Posix where the specification of the TZ
* environment restricts the combined offset for time zone and
* Daylight Savings Time to 2 * (24:59:59), just under 50 hours.
*
*Entry:
* __time64_t *ptime - pointer to a long time value
*
*Exit:
* errno_t = 0 success
* tm members filled-in
* errno_t = non zero
* tm members initialized to -1 if ptm != NULL
*
*Exceptions:
* See items (3) and (4) in the NOTES above. If these assumptions are
* violated, behavior is undefined.
*
*******************************************************************************/

errno_t __cdecl _localtime64_s (
struct tm *ptm,
const __time64_t *ptime
)
{
__time64_t ltime;
errno_t e = 0;
int daylight = 0;
long dstbias = 0;
long timezone = 0;

_VALIDATE_RETURN_ERRCODE( ( ptm != NULL ), EINVAL )
memset( ptm, 0xff, sizeof( struct tm ) );

_VALIDATE_RETURN_ERRCODE( ( ptime != NULL ), EINVAL )

/*
* Check for illegal __time64_t value
*/
_VALIDATE_RETURN_ERRCODE_NOEXC( (*ptime >= 0), EINVAL);
_VALIDATE_RETURN_ERRCODE( (*ptime <= _MAX__TIME64_T), EINVAL);

__tzset();

_ERRCHECK(_get_daylight(&daylight));
_ERRCHECK(_get_dstbias(&dstbias));
_ERRCHECK(_get_timezone(&timezone));

if ( *ptime > 3 * _DAY_SEC ) {
/*
* The date does not fall within the first three representable
* days of the Epoch. Therefore, there is no possibility of
* underflowing the __time64_t representation as we compensate
* for timezone and Daylight Savings Time.
*/

ltime = *ptime - timezone;
e = _gmtime64_s( ptm, <ime );
if ( e != 0)
{
return e;
}

/*
* Check and adjust for Daylight Saving Time.
*/
if ( daylight && _isindst( ptm ) ) {
ltime -= dstbias;
e = _gmtime64_s( ptm, <ime );
if ( e != 0 )
{
return e;
}
ptm->tm_isdst = 1;
}
}
else {
e = _gmtime64_s( ptm, ptime );
if ( e != 0 )
{
return e;
}

/*
* The date falls with the first three days of the Epoch.
* It is possible the time_t representation would underflow
* while compensating for timezone and Daylight Savings Time
* Therefore, make the timezone and Daylight Savings Time
* adjustments directly in the tm structure. The beginning of
* the Epoch is 00:00:00, 01-01-70 (UTC).
*
* First, adjust for the timezone.
*/
if ( daylight && _isindst(ptm) ) {
ltime = (__time64_t)ptm->tm_sec - (timezone + dstbias);
ptm->tm_isdst = 1;
}
else
ltime = (__time64_t)ptm->tm_sec - timezone;

ptm->tm_sec = (int)(ltime % 60);
if ( ptm->tm_sec < 0 ) {
ptm->tm_sec += 60;
ltime -= 60;
}

ltime = (__time64_t)ptm->tm_min + ltime/60;
ptm->tm_min = (int)(ltime % 60);
if ( ptm->tm_min < 0 ) {
ptm->tm_min += 60;
ltime -= 60;
}

ltime = (__time64_t)ptm->tm_hour + ltime/60;
ptm->tm_hour = (int)(ltime % 24);
if ( ptm->tm_hour < 0 ) {
ptm->tm_hour += 24;
ltime -=24;
}

ltime /= 24;

if ( ltime > 0 ) {
/*
* There is no possibility of overflowing the tm_mday
* and tm_yday fields since the date can be no later
* than January 19.
*/
ptm->tm_wday = (ptm->tm_wday + (int)ltime) % 7;
ptm->tm_mday += (int)ltime;
ptm->tm_yday += (int)ltime;
}
else if ( ltime < 0 ) {
/*
* It is possible to underflow the tm_mday and tm_yday
* fields. If this happens, then adjusted date must
* lie in December 1969.
*/
ptm->tm_wday = (ptm->tm_wday + 7 + (int)ltime) % 7;
if ( (ptm->tm_mday += (int)ltime) <= 0 ) {
ptm->tm_mday += 31;
// according to assumption 4 above, timezone can
// cause the date to underflow the epoch by
// more than a day
ptm->tm_yday = ptm->tm_yday + (int)ltime + 365;
ptm->tm_mon = 11;
ptm->tm_year--;
}
else {
ptm->tm_yday += (int)ltime;
}
}
}


return 0;
}

/***
*struct tm *_localtime64(ptime) - convert __time64_t value to tm structure
*
*Purpose:
* Convert a value in 64-bit internal (__time64_t) format to a tm struct
* containing the corresponding local time.
*
* NOTES:
* (1) gmtime must be called before _isindst to ensure that the tb time
* structure is initialized.
* (2) gmtime, _gtime64, localtime and _localtime64() all use a single
* statically allocated buffer. Each call to one of these routines
* destroys the contents of the previous call.
* (3) It is assumed that __time64_t is a 64-bit integer representing
* the number of seconds since 00:00:00, 01-01-70 (UTC) (i.e., the
* Posix/Unix Epoch. Only non-negative values are supported.
* (4) It is assumed that the maximum adjustment for local time is
* less than three days (include Daylight Savings Time adjustment).
* This only a concern in Posix where the specification of the TZ
* environment restricts the combined offset for time zone and
* Daylight Savings Time to 2 * (24:59:59), just under 50 hours.
*
*Entry:
* __time64_t *ptime - pointer to a long time value
*
*Exit:
* If *ptime is non-negative, returns a pointer to the tm structure.
* Otherwise, returns NULL.
*
*Exceptions:
* See items (3) and (4) in the NOTES above. If these assumptions are
* violated, behavior is undefined.
*
*******************************************************************************/

struct tm * __cdecl _localtime64 (
const __time64_t *ptime
)
{
errno_t e;
struct tm *ptm = __getgmtimebuf();
if ( ptm == NULL )
{
return NULL;
}

e = _localtime64_s( ptm, ptime );
if ( e != 0 )
{
return NULL;
}
return ptm;
}
Nio96 2009-08-19
  • 打赏
  • 举报
回复
有谁能提供一下localtime()的源码吗?

谢谢
Nio96 2009-08-19
  • 打赏
  • 举报
回复
再顶一下.

如果我现在拿到了从1970年到现在所经过的秒数,我应该如何确定今天是星期几呢?
Nio96 2009-08-17
  • 打赏
  • 举报
回复
li.QuadPart += (LONGLONG)10000000 * ulTime;

为什么ulTime要乘以100000000 ? 对其中的算法不是很明了
goodname 2009-08-17
  • 打赏
  • 举报
回复
1第一个问题是否本地时间取决于是什么协议,如果是自己家定义的私有协议,那想什么定义就怎么定义。
一般ntp,sntp协议都是用utc时间的。sntp服务器比较多。sntp使用udp。
2这段函数其实就是首先是用1970-1-1标准时间初始化一个st结构,然后将st结构转化为一个数字,
这个数字累加上ulTime,这个新的数字就是需要的时间了,将这个再转回去就是了。
因为SetSystemTime需要一个SYSTEMTIME,不然的话怎么做,直接将ulTime加到 st.wSecond 吗?

3c语言的可以使用mktime,gmtime等函数。


Nio96 2009-08-17
  • 打赏
  • 举报
回复
谢谢楼上的回复.
1.但是我是直接connect服务器后接收到回来的时间,并没有对其进行时区的判断及相应的操作,而解析出来的时间已经是对的,所以我怀疑是已经是根据时区发回来的秒数.

2. 不是很明白st filetime之间是什么关系? 如下的几句是如何把秒数转换成当前的系统时间的?

li.QuadPart += (LONGLONG)10000000 * ulTime;
ft = *(FILETIME*)&li;
FileTimeToSystemTime(&ft, &st);
SetSystemTime(&st);

3.C语言库的函数都有哪几个可以用?不是很熟悉这一块.
goodname 2009-08-17
  • 打赏
  • 举报
回复
1一般通信中网络传输都是用utc时间,客户端接收后自己根据时区调整成本地时间展示给用户。
2只是得到了一个时间差ulTime的话,这么做是为了给定的时间转成结构SYSTEMTIME st
你也可以使用c语言库中的函数进行转化。
kakashi0309 2009-08-17
  • 打赏
  • 举报
回复
楼上正解
goodname 2009-08-17
  • 打赏
  • 举报
回复
根据msdn上的说法

FILETIME Structure

Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).

大概是100纳秒为单位。

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧