i have managed to make a NTP request and retrieve the server time from it's NTP response. i want to convert this number to a Human-readable time, writing in C++. can some one help me ? as example you can look at: http://www.4webhelp.net/us/timestamp.php?action=stamp&stamp=771554255&timezone=0 once you set the timestamp to 771554255 you'll get "29开发者_运维知识库/7/2010 13:14:32". i wanna do the same in my code, any help ?
It's not C++, but here's a perl implementation. Converting this into C++ should be no big deal:
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);
Here is my solution to this problem. It's more simplified replica of the PERL code mentioned in the accepted answer.
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);
}
Then just use it like this:
timestamp_to_str(unix_to_ntp(...));
Here is the C++ code for you.. but this is not it.. The windows api used here does the required but there is a great mathematical calculation behind it.. Its a big pain to understand so I didn't put it here. For class "CSNTPClient" u will have to copy and paste the header "sntp.h" content from URL ".htm">http://read.pudn.com/downloads160/sourcecode/windows/comm/720007/SntpTest/Sntp.h_.htm". This is a modified version of PJ Naughters code example.. and there u go... Cheers !!
#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);
}
}
精彩评论