4

我已经设法发出一个 NTP 请求并从它的 NTP 响应中检索服务器时间。我想将此数字转换为人类可读的时间,用 C++ 编写。有人能帮我吗 ?例如,您可以查看: http ://www.4webhelp.net/us/timestamp.php?action=stamp&stamp=771554255&timezone= 0 一旦您将时间戳设置为 771554255,您将获得“29/7/2010 13:14 :32"。我想在我的代码中做同样的事情,有什么帮助吗?

4

3 回答 3

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);
于 2010-07-29T13:28:13.747 回答
0

这是我对这个问题的解决方案。它是已接受答案中提到的 PERL 代码的更简化副本。

void unix_to_ntp(uint32_t& timestamp) {
    /**
     * Unix uses an epoch located at 1.1.1970 - 00:00h (UTC)
     * and NTP uses 1.1.1900 - 00:00h (UTC) which leads to an
     * offset equivalent to 70 years in seconds (note that
     * there are 17 leap years between the two dates)
     */
    constexpr uint8_t  NTP_UNIX_OFFSET_YEARS = 70;
    constexpr uint16_t DAYS_IN_YEAR          = 365;
    constexpr uint8_t  NUMBER_OF_LEAP_YEARS  = 17;
    constexpr uint32_t SECONDS_IN_DAY        = 86400;
    constexpr uint32_t NTP_UNIX_OFFSET_SECONDS =
        (NTP_UNIX_OFFSET_YEARS * DAYS_IN_YEAR + NUMBER_OF_LEAP_YEARS) * SECONDS_IN_DAY;

    timestamp = timestamp - NTP_UNIX_OFFSET_SECONDS;
}

uint32_t unix_to_ntp(uint32_t const& timestamp) {
    uint32_t tmp = timestamp;
    unix_to_ntp(tmp);
    return tmp;
}

std::string timestamp_to_str(uint32_t const& timestamp) {
    struct tm *t;
    char buffer[20];
    long int tmp = timestamp;
    t = gmtime(&tmp);
    strftime(buffer, sizeof(buffer), "%F %T", t);
    return std::string(buffer);
}

然后像这样使用它:

timestamp_to_str(unix_to_ntp(...));
于 2019-09-15T20:01:46.680 回答
-1

这是给你的C++代码..但这不是..这里使用的windows api可以满足要求,但它背后有一个很好的数学计算..理解起来很痛苦,所以我没有把它放在这里。对于“CSNTPClient”类,您必须从 URL“.htm”>http://read.pudn.com/downloads160/sourcecode/windows/comm/720007/SntpTest/Sntp 复制并粘贴标题“sntp.h”内容.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);
    }
}
于 2013-06-01T13:00:01.543 回答