- A NTP timestamp consists of a 32-bit part for second and a 32-bit part for fraction second. And the unit of the fraction part is 2-32 second.
- A UNIX Struct timeval consists of a 32-bit part for second and a 32-bit part for micro-second.
- A NTP timestamp is defined as the number of seconds have elapsed since Jan 1, 1900.
- A UNIX struct timeval is defined as the number of seconds have elapsed since Jan 1, 1970.
struct ntp_time_t { uint32_t second; uint32_t fraction; };
And the knowned timeval structure of UNIX is
struct timeval { uint32_t tv_sec; uint32_t tv_usec; };
To convert from NTP timestamp to UNIX timeval, we need to offset the second field and
transform the fraction part:
void convert_ntp_time_into_unix_time(struct ntp_time_t *ntp, struct timeval *unix) { unix->tv_sec = ntp->second - 0x83AA7E80; // the seconds from Jan 1, 1900 to Jan 1, 1970 unix->tv_usec = (uint32_t)( (double)ntp->fraction * 1.0e6 / (double)(1LL<<32) ); } void convert_unix_time_into_ntp_time(struct timeval *unix, struct ntp_time_t *ntp) { ntp->second = unix->tv_sec + 0x83AA7E80; ntp->fraction = (uint32_t)( (double)(unix->tv_usec+1) * (double)(1LL<<32) * 1.0e-6 ); }
Example:
#include <sys/time.h> #include <stdio.h> #include <stdint.h> struct ntp_time_t { uint32_t second; uint32_t fraction; }; void convert_ntp_time_into_unix_time(struct ntp_time_t *ntp, struct timeval *unix) { unix->tv_sec = ntp->second - 0x83AA7E80; // the seconds from Jan 1, 1900 to Jan 1, 1970 unix->tv_usec = (uint32_t)( (double)ntp->fraction * 1.0e6 / (double)(1LL<<32) ); } void convert_unix_time_into_ntp_time(struct timeval *unix, struct ntp_time_t *ntp) { ntp->second = unix->tv_sec + 0x83AA7E80; ntp->fraction = (uint32_t)( (double)(unix->tv_usec+1) * (double)(1LL<<32) * 1.0e-6 ); } int main() { struct ntp_time_t ntp; struct timeval unix; // get time unix time via gettimeofday gettimeofday(&unix, NULL); printf("UNIX Time: %ld %ld\n", unix.tv_sec, unix.tv_usec); // convert unix time to ntp time convert_unix_time_into_ntp_time(&unix, &ntp); printf("NTP Time: %ld %ld\n", ntp.second, ntp.fraction); // convert ntp time back to unix time to see whether they are same convert_ntp_time_into_unix_time(&ntp, &unix); printf("UNIX Time: %ld %ld\n", unix.tv_sec, unix.tv_usec); }
Output:
UNIX Time: 1340097242 933680 NTP Time: 3549086042 4010129359 UNIX Time: 1340097242 933680
Superb Example Thanks a Lot for Info
ReplyDeleteThanks. I used your code to make a NTP to RFC3306 for my logging project.
ReplyDeletehttps://github.com/cameronkerrnz/libipfix/blob/master/lib/json_out.c
I'm not a developer, i always use the free online timestamp generator to create the unix timestamp.
ReplyDeleteplease check ntp->fraction = (uint32_t)( (double)(unix->tv_usec+1) * (double)(1LL<<32) * 1.0e-6 ); how about this ntp->fraction = (uint32_t)( (double)(unix->tv_usec) * (double)(1LL<<32 - 1) * 1.0e-6 );
ReplyDelete