NTP rollover-safe design with ESP8266 (Curiosity)
What's the most polite way to tell a manager "shut up and let me work"?
Opposite of "Squeaky wheel gets the grease"
Why does a helium balloon rise?
Show sparse matrices like chessboards
Asking bank to reduce APR instead of increasing credit limit
Rotated Position of Integers
Could the Missouri River be running while Lake Michigan was frozen several meters deep?
Working in the USA for living expenses only; allowed on VWP?
Short story written from alien perspective with this line: "It's too bright to look at, so they don't"
Why is Colorado so different politically from nearby states?
Comma Code - Ch. 4 Automate the Boring Stuff
Does it cost a spell slot to cast a spell from a Ring of Spell Storing?
Did thousands of women die every year due to illegal abortions before Roe v. Wade?
What is a simple, physical situation where complex numbers emerge naturally?
NTP rollover-safe design with ESP8266 (Curiosity)
Initialize an array of doubles at compile time
Responsibility for visa checking
How can I make 20-200 ohm variable resistor look like a 20-240 ohm resistor?
Credit card offering 0.5 miles for every cent rounded up. Too good to be true?
How can Iron Man's suit withstand this?
Unconventional Opposites
Do marked cards or loaded dice have any mechanical benefit?
What happens if you do emergency landing on a US base in middle of the ocean?
Hygienic footwear for prehensile feet?
NTP rollover-safe design with ESP8266 (Curiosity)
The Arduino NTP implementation is rather naive in some respects. It basically just grabs the time in seconds from the raw packet, and then converts it to Unix time via subtraction. How would it be possible to create an implementation that is safe from at least this next NTP rollover (due in 2036)? I'd rather not design something that might suddenly fail in strange ways in a decade or two when I have forgotten why it might do so (but it's not horribly important if it's not easily fixed).
If it can make it to 2100, I'd have larger problems (the RTC would crap itself), so just this rollover is fine.
The existing implementation (https://github.com/arduino-libraries/NTPClient/blob/master/NTPClient.cpp):
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
this->_currentEpoc = secsSince1900 - SEVENZYYEARS;
esp8266 time
add a comment |
The Arduino NTP implementation is rather naive in some respects. It basically just grabs the time in seconds from the raw packet, and then converts it to Unix time via subtraction. How would it be possible to create an implementation that is safe from at least this next NTP rollover (due in 2036)? I'd rather not design something that might suddenly fail in strange ways in a decade or two when I have forgotten why it might do so (but it's not horribly important if it's not easily fixed).
If it can make it to 2100, I'd have larger problems (the RTC would crap itself), so just this rollover is fine.
The existing implementation (https://github.com/arduino-libraries/NTPClient/blob/master/NTPClient.cpp):
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
this->_currentEpoc = secsSince1900 - SEVENZYYEARS;
esp8266 time
add a comment |
The Arduino NTP implementation is rather naive in some respects. It basically just grabs the time in seconds from the raw packet, and then converts it to Unix time via subtraction. How would it be possible to create an implementation that is safe from at least this next NTP rollover (due in 2036)? I'd rather not design something that might suddenly fail in strange ways in a decade or two when I have forgotten why it might do so (but it's not horribly important if it's not easily fixed).
If it can make it to 2100, I'd have larger problems (the RTC would crap itself), so just this rollover is fine.
The existing implementation (https://github.com/arduino-libraries/NTPClient/blob/master/NTPClient.cpp):
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
this->_currentEpoc = secsSince1900 - SEVENZYYEARS;
esp8266 time
The Arduino NTP implementation is rather naive in some respects. It basically just grabs the time in seconds from the raw packet, and then converts it to Unix time via subtraction. How would it be possible to create an implementation that is safe from at least this next NTP rollover (due in 2036)? I'd rather not design something that might suddenly fail in strange ways in a decade or two when I have forgotten why it might do so (but it's not horribly important if it's not easily fixed).
If it can make it to 2100, I'd have larger problems (the RTC would crap itself), so just this rollover is fine.
The existing implementation (https://github.com/arduino-libraries/NTPClient/blob/master/NTPClient.cpp):
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
this->_currentEpoc = secsSince1900 - SEVENZYYEARS;
esp8266 time
esp8266 time
edited 7 hours ago
VE7JRO♦
1,80251324
1,80251324
asked 9 hours ago
RDragonrydrRDragonrydr
429
429
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
This implementation is perfectly fine. The calculations are done with
unsigned numbers, so they are naturally rollover safe. The day NTP time
rolls over, secsSince1900
will become a very small number, and
subtracting SEVENZYYEARS
from it will cause an extra roll over. Owing
to the rules of modular arithmetics, these two rollovers compensate and
you are guaranteed to get the correct result modulo
232 s.
In the end, you get a Unix time as an unsigned 32-bit integer. Unix time
is traditionally signed, which makes the 32-bit representation roll over
in January 2038. The authors of this library have instead chosen to
represent it as an unsigned number, which means it will roll over in
February 2106.
Huh. That's actually rather cool. I knew of a similar method for millis(), but didn't know this worked for NTP as well. Thanks!
– RDragonrydr
7 hours ago
@RDragonrydr: carry propagates from low to high in addition/subtraction. The low bits of the result do not depend on any higher bit positions, so if you want a 32-bit result it's always safe to truncate your inputs instead of doing a 64-bit subtract and truncating the result. Same for left shift, or the lowN
bits of anN x N
multiply. See also Which 2's complement integer operations can be used without zeroing high bits in the inputs, if only the low part of the result is wanted?
– Peter Cordes
10 mins ago
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
return StackExchange.using("schematics", function ()
StackExchange.schematics.init();
);
, "cicuitlab");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "540"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2farduino.stackexchange.com%2fquestions%2f65883%2fntp-rollover-safe-design-with-esp8266-curiosity%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
This implementation is perfectly fine. The calculations are done with
unsigned numbers, so they are naturally rollover safe. The day NTP time
rolls over, secsSince1900
will become a very small number, and
subtracting SEVENZYYEARS
from it will cause an extra roll over. Owing
to the rules of modular arithmetics, these two rollovers compensate and
you are guaranteed to get the correct result modulo
232 s.
In the end, you get a Unix time as an unsigned 32-bit integer. Unix time
is traditionally signed, which makes the 32-bit representation roll over
in January 2038. The authors of this library have instead chosen to
represent it as an unsigned number, which means it will roll over in
February 2106.
Huh. That's actually rather cool. I knew of a similar method for millis(), but didn't know this worked for NTP as well. Thanks!
– RDragonrydr
7 hours ago
@RDragonrydr: carry propagates from low to high in addition/subtraction. The low bits of the result do not depend on any higher bit positions, so if you want a 32-bit result it's always safe to truncate your inputs instead of doing a 64-bit subtract and truncating the result. Same for left shift, or the lowN
bits of anN x N
multiply. See also Which 2's complement integer operations can be used without zeroing high bits in the inputs, if only the low part of the result is wanted?
– Peter Cordes
10 mins ago
add a comment |
This implementation is perfectly fine. The calculations are done with
unsigned numbers, so they are naturally rollover safe. The day NTP time
rolls over, secsSince1900
will become a very small number, and
subtracting SEVENZYYEARS
from it will cause an extra roll over. Owing
to the rules of modular arithmetics, these two rollovers compensate and
you are guaranteed to get the correct result modulo
232 s.
In the end, you get a Unix time as an unsigned 32-bit integer. Unix time
is traditionally signed, which makes the 32-bit representation roll over
in January 2038. The authors of this library have instead chosen to
represent it as an unsigned number, which means it will roll over in
February 2106.
Huh. That's actually rather cool. I knew of a similar method for millis(), but didn't know this worked for NTP as well. Thanks!
– RDragonrydr
7 hours ago
@RDragonrydr: carry propagates from low to high in addition/subtraction. The low bits of the result do not depend on any higher bit positions, so if you want a 32-bit result it's always safe to truncate your inputs instead of doing a 64-bit subtract and truncating the result. Same for left shift, or the lowN
bits of anN x N
multiply. See also Which 2's complement integer operations can be used without zeroing high bits in the inputs, if only the low part of the result is wanted?
– Peter Cordes
10 mins ago
add a comment |
This implementation is perfectly fine. The calculations are done with
unsigned numbers, so they are naturally rollover safe. The day NTP time
rolls over, secsSince1900
will become a very small number, and
subtracting SEVENZYYEARS
from it will cause an extra roll over. Owing
to the rules of modular arithmetics, these two rollovers compensate and
you are guaranteed to get the correct result modulo
232 s.
In the end, you get a Unix time as an unsigned 32-bit integer. Unix time
is traditionally signed, which makes the 32-bit representation roll over
in January 2038. The authors of this library have instead chosen to
represent it as an unsigned number, which means it will roll over in
February 2106.
This implementation is perfectly fine. The calculations are done with
unsigned numbers, so they are naturally rollover safe. The day NTP time
rolls over, secsSince1900
will become a very small number, and
subtracting SEVENZYYEARS
from it will cause an extra roll over. Owing
to the rules of modular arithmetics, these two rollovers compensate and
you are guaranteed to get the correct result modulo
232 s.
In the end, you get a Unix time as an unsigned 32-bit integer. Unix time
is traditionally signed, which makes the 32-bit representation roll over
in January 2038. The authors of this library have instead chosen to
represent it as an unsigned number, which means it will roll over in
February 2106.
answered 8 hours ago
Edgar BonetEdgar Bonet
25.5k22546
25.5k22546
Huh. That's actually rather cool. I knew of a similar method for millis(), but didn't know this worked for NTP as well. Thanks!
– RDragonrydr
7 hours ago
@RDragonrydr: carry propagates from low to high in addition/subtraction. The low bits of the result do not depend on any higher bit positions, so if you want a 32-bit result it's always safe to truncate your inputs instead of doing a 64-bit subtract and truncating the result. Same for left shift, or the lowN
bits of anN x N
multiply. See also Which 2's complement integer operations can be used without zeroing high bits in the inputs, if only the low part of the result is wanted?
– Peter Cordes
10 mins ago
add a comment |
Huh. That's actually rather cool. I knew of a similar method for millis(), but didn't know this worked for NTP as well. Thanks!
– RDragonrydr
7 hours ago
@RDragonrydr: carry propagates from low to high in addition/subtraction. The low bits of the result do not depend on any higher bit positions, so if you want a 32-bit result it's always safe to truncate your inputs instead of doing a 64-bit subtract and truncating the result. Same for left shift, or the lowN
bits of anN x N
multiply. See also Which 2's complement integer operations can be used without zeroing high bits in the inputs, if only the low part of the result is wanted?
– Peter Cordes
10 mins ago
Huh. That's actually rather cool. I knew of a similar method for millis(), but didn't know this worked for NTP as well. Thanks!
– RDragonrydr
7 hours ago
Huh. That's actually rather cool. I knew of a similar method for millis(), but didn't know this worked for NTP as well. Thanks!
– RDragonrydr
7 hours ago
@RDragonrydr: carry propagates from low to high in addition/subtraction. The low bits of the result do not depend on any higher bit positions, so if you want a 32-bit result it's always safe to truncate your inputs instead of doing a 64-bit subtract and truncating the result. Same for left shift, or the low
N
bits of an N x N
multiply. See also Which 2's complement integer operations can be used without zeroing high bits in the inputs, if only the low part of the result is wanted?– Peter Cordes
10 mins ago
@RDragonrydr: carry propagates from low to high in addition/subtraction. The low bits of the result do not depend on any higher bit positions, so if you want a 32-bit result it's always safe to truncate your inputs instead of doing a 64-bit subtract and truncating the result. Same for left shift, or the low
N
bits of an N x N
multiply. See also Which 2's complement integer operations can be used without zeroing high bits in the inputs, if only the low part of the result is wanted?– Peter Cordes
10 mins ago
add a comment |
Thanks for contributing an answer to Arduino Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2farduino.stackexchange.com%2fquestions%2f65883%2fntp-rollover-safe-design-with-esp8266-curiosity%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown