2010-07-29 316 views
3

我設法發出NTP請求,並從NTP響應中檢索服務器時間。 我想將這個數字轉換爲人類可讀的時間,用C++編寫。 有人能幫助我嗎? 作爲例子,你可以看看: http://www.4webhelp.net/us/timestamp.php?action=stamp&stamp=771554255&timezone=0 一旦你設置時間戳771554255你會得到「29/7/2010 13:14:32」。 我想在我的代碼中做同樣的事情, 有幫助嗎?將NTP時間轉換爲人類可讀的時間

+1

作爲第一個答案mentionned,你指向的頁面不處理NTP時間戳(從1900年1月1日開始,64位,秒+秒),但是使用Unix時間(從1970年1月1日開始,32位,秒) – pascal 2010-07-29 13:45:44

+1

作爲一個短命的用一個Perl樣本),你只需要拿到前32位,從1900年1月1日到1970年1月1日(大約70 * 365.25 * 24 * 3600),刪除秒數,並且你有一個Unix時間()兼容價值... – pascal 2010-07-29 13:50:27

+1

Jus t用於檢查,32位提供了NTP時間戳的秒數,自1968年以來設置了高位位...所以,作爲有符號整數,它看起來是負的。 – pascal 2010-07-29 13:54:08

回答

3

這不是C++,但是這是一個perl實現。轉換成C++,這應該是沒有什麼大不了的:

http://www.ntp.org/ntpfaq/NTP-s-related.htm#AEN6780

# usage: perl n2u.pl timestamp 
# timestamp is either decimal: [0-9]+.?[0-9]* 
# or hex: (0x)?[0-9]+.?(0x)?[0-9]* 

# Seconds between 1900-01-01 and 1970-01-01 
my $NTP2UNIX = (70 * 365 + 17) * 86400; 

my $timestamp = shift; 
die "Usage perl n2u.pl timestamp (with or without decimals)\n" 
    unless ($timestamp ne ""); 

my ($i, $f) = split(/\./, $timestamp, 2); 
$f ||= 0; 
if ($i =~ /^0x/) { 
    $i = oct($i); 
    $f = ($f =~ /^0x/) ? oct($f)/2 ** 32 : "0.$f"; 
} else { 
    $i = int($i); 
    $f = $timestamp - $i; 
} 

my $t = $i - $NTP2UNIX; 
while ($t < 0) { 
    $t += 65536.0 * 65536.0; 
} 

my ($year, $mon, $day, $h, $m, $s) = (gmtime($t))[5, 4, 3, 2, 1, 0]; 
$s += $f; 

printf("%d-%02d-%02d %02d:%02d:%06.3f\n", 
     $year + 1900, $mon+1, $day, $h, $m, $s); 
+0

因爲它是perl而不是C++,所以我首先在發佈時猶豫了一下。但是這個方法是正確的,並且可以很容易地移植到C++中。 – NinjaCat 2010-07-29 15:14:09

+0

它給了我目前在二十世紀八十年代的時間? – Stef 2014-05-19 07:20:25

-1

這裏是你的C++代碼..但這不是它..這裏使用的Windows API的確實需要的,但有一個偉大的數學計算背後..它是一個很大的理解痛苦,所以我沒有把它放在這裏。對於「CSNTPClient」類,你將不得不從URL複製和粘貼標題「sntp.h」內容。「http://hk.pvn.com/downloads160/sourcecode/windows/comm/720007/SntpTest/Sntp .h_.htm」這是PJ Naughters代碼示例的修改版本..有ü去...乾杯!!

#include "stdafx.h" 
int main() 
{ 
    //Initialise the winsock stack 
    WSADATA wsaData; 
    BYTE wsMajorVersion = 1; 
    BYTE wsMinorVersion = 1; 
    WORD wVersionRequested = MAKEWORD(wsMinorVersion, wsMajorVersion); 
    if (WSAStartup(wVersionRequested, &wsaData) != 0) 
    { 
     _tprintf(_T("Failed to load winsock stack\n")); 
     return 1; 
    } 
    if (LOBYTE(wsaData.wVersion) != wsMajorVersion || HIBYTE(wsaData.wVersion) != wsMinorVersion) 
    { 
     _tprintf(_T("Winsock stack does not support version which this program requires\n")); 
     WSACleanup(); 
     return 1; 
    } 

    //Do the actual NTP Query 
    CSNTPClient sntp; 
    NtpServerResponse response; 
    if (sntp.GetServerTime(specify ntp server url or ip, response)) 
    { 
     _tprintf(_T("Time was successfully retreived from NTP server\n")); 

     SYSTEMTIME st1 = response.m_OriginateTime; 
     SYSTEMTIME st2 = response.m_ReceiveTime; 
     SYSTEMTIME st3 = response.m_TransmitTime; 
     SYSTEMTIME st4 = response.m_DestinationTime; 

     cout << response.m_DestinationTime << endl; 

     TIME_ZONE_INFORMATION lpTimeZoneInfo; 
     GetTimeZoneInformation(&lpTimeZoneInfo); //Get the local TIME ZONE 
     SYSTEMTIME stLocal; 
     //To Get Local Time from the fetched GMT/UTC Time from the server, use SystemTimeToTzSpecificLocalTime() 
     //To get GMT/UTC Time from Local Time, use the API TzSpecificLocalTimeToSystemTime() 
     SystemTimeToTzSpecificLocalTime(&lpTimeZoneInfo, &st3, &stLocal); 

     _tprintf(_T("\n")); 
     _tprintf(_T("       DD/MM/YYYY HH:MM:SS.MS\n")); 
     _tprintf(_T("\n\n\nObtaining Time thru API SystemTimeToTzSpecificLocalTime :\n\n")); 
     _tprintf(_T("Server Transmit Date was %02d/%02d/%04d, %02d:%02d:%02d.%03d\n"), st3.wDay, st3.wMonth, st3.wYear, st3.wHour, st3.wMinute, st3.wSecond, st3.wMilliseconds); 
     _tprintf(_T("Client Destination Date was %02d/%02d/%04d, %02d:%02d:%02d.%03d\n"), stLocal.wDay, stLocal.wMonth, stLocal.wYear, stLocal.wHour, stLocal.wMinute, stLocal.wSecond, stLocal.wMilliseconds); 
    } 
} 
+0

嘿,一個獨立的解決方案和它的描述會更好,我認爲。 – Aldream 2013-06-01 13:24:01

相關問題