Mariana Ferreira Mariana Ferreira - 1 month ago 7x
C Question

NTP convert seconds since 1st january 1900 to current date

I'm programming embedded so I'm not able to use many of the c libraries.

I've used the NTP protocol so I now have the number of seconds since the 1st January 1900. Now I need to convert it in a meaningful timestamp. I've been searching about it and I've found this @R.. implementation.

I've tried to use it but I'm not getting a correct result.

Does someone know what is the first argument of the function? I've tried to pass the numer of seconds since the 1st of January 1900 and the number of seconds since 1st of January 1970 but none of them worked as expected.

The code I'm running is:

#define NTP_PACKET_SIZE 48
uint8_t packetBuffer[ NTP_PACKET_SIZE];
typedef struct tempo{
int tm_sec; /* seconds, range 0 to 59 */
int tm_min; /* minutes, range 0 to 59 */
int tm_hour; /* hours, range 0 to 23 */
int tm_mday; /* day of the month, range 1 to 31 */
int tm_mon; /* month, range 0 to 11 */
int tm_year; /* The number of years since 1900 */
int tm_wday; /* day of the week, range 0 to 6 */
int tm_yday; /* day in the year, range 0 to 365 */
int tm_isdst; /* daylight saving time */
} tim;

tim * t;

static returnTypes_t bsdUdpClient(uint16_t AddrSize){

int16_t Status = (int16_t) ZERO;

memset(packetBuffer, 0, NTP_PACKET_SIZE);

// Initialize values needed to form NTP request
packetBuffer[0] = 0xE3; //0b11100011; // LI, Version, Mode
packetBuffer[1] = 0x00; // Stratum, or type of clock
packetBuffer[2] = 0x06; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;

SockID = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, (uint32_t) ZERO);
if (SockID < (int16_t) ZERO)
return (SOCKET_ERROR);

Status = sl_SendTo(SockID, packetBuffer, NTP_PACKET_SIZE * sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, AddrSize);

/*Check if 0 transmitted bytes sent or error condition*/
if (Status <= (int16_t) ZERO) {
return (SEND_ERROR);
printf("request sent successfully\n\r");

/* receive the reply from the server*/
Status = sl_RecvFrom(SockID, packetBuffer, NTP_PACKET_SIZE * sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, &AddrSize);
if (Status < (int16_t) ZERO){
printf("error - no bytes received: %d\n\r", (int16_t)Status);
printf("reply received\n\r");

Status = sl_Close(SockID);
if (Status < 0)
printf("problem on sl_Close\n\r");

uint8_t index3 = packetBuffer[40];
uint8_t index2 = packetBuffer[41];
uint8_t index1 = packetBuffer[42];
uint8_t index0 = packetBuffer[43];

uint16_t highWord = index3 << 8 | index2;
uint16_t lowWord = index1 << 8 | index0;

uint32_t secondsSince1900 = highWord << 16 | lowWord;

printf("Seconds since 1 Janeiro de 1900: %lu\n\r", secondsSince1900);
printf("Seconds since 1 Janeira de 1970: %lu\n\r", secondsSince1900 - 2208988800ul );

if(secs_to_date( (secondsSince1900 - 2208988800ul) , t)!=0)
printf("impossible to convert\n\r");

printf("year: %d; month: %d; day:%d; hour:%d; minuts: %d; seconds:%d\n\r", t->tm_year, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec );

return (STATUS_OK);


So, for example, I runned the code a few minuts ago, I was expecting the result

year:2016;month:9;day:1;hour:9;minuts:20;seconds:56 (for example)

but I got this

year: 32281; month: 32279; day:32277; hour:32275; minuts: 32221; seconds:537001984.


Do you make t point anywhere valid somewhere? Because it's an uninitialized global variable it will be zero-initialized, which means the pointer will be initialized to NULL. Dereferencing a null pointer leads to undefined behavior.

Instead of declaring it as a pointer just declare it as a normal non-pointer variable:

tim t;

Then use the address-of operator & when you call the conversion function

secs_to_date( (secondsSince1900 - 2208988800ul) , &t)
//                                                ^
//                                                |
//   Notice the use of the address-of operator here