-
-
Notifications
You must be signed in to change notification settings - Fork 753
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Daylight Savings Time support #2230
Conversation
src/jswrap_espruino.c
Outdated
|
||
if (!jsvIsArray(params)) return; | ||
if (jsvGetLength(params) != 12) return; | ||
jsvIteratorNew(&it,params,JSIF_DEFINED_ARRAY_ElEMENTS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would just replacing the following with jswrap_typedarray_constructor(ARRAYBUFFERVIEW_INT16, params, 0, 0)
work here? It'd save a bit of code space
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably. Still familiarising myself with the data types.
} | ||
|
||
// Convert a number of days since 1970 into y,m,d. 0<=m<=11 | ||
void getDateFromDayNumber(int day, int *y, int *m, int *date) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any kind of reference for this that could be linked? This looks a lot like witchcraft to me and it might just be handy to know where it came from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is adopted from an algorithm in a book called "Astronomical Algorithms" by Jean Meeus. The book - from 1991 - is well out of print by now.
I'm in the process of doing my own write-up on these algorithms. I've managed to convince myself of the correctness of everything but the constant 2877911. I've also ran getDayNumberFromDate against getDateFromDayNumber, and they are consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! It's a magic bit of code - very few people doing stuff like that any more :) Just a reference to "Astronomical Algorithms" would be fine but a link to your writeup seems even better ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to do quite a bit of work to the algorithm in "Astronomical Algorithms", as it had its year zero in the year 4713BC. I wanted my year zero to be 1970 to correspond with the zero of Unix time, and the conversion was quite the mind bend.
I just love algorithms like that - it was a joy to work on!
src/jswrap_date.c
Outdated
jsvArrayBufferIteratorNew(&it, dst, 0); | ||
y = 0; | ||
while (y < 12) { | ||
JsVar *setting = jsvArrayBufferIteratorGetValue(&it); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please could you use dstSetting[y++]=jsvArrayBufferIteratorGetIntegerValue(&it)
here? We try and avoid accessing ->varData
directly usually (eg using jsvGetInteger
) as it makes it easier if we need to tweak the internals.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
"type" : "method", | ||
"class" : "Date", | ||
"name" : "toLocalISOString", | ||
"generate" : "jswrap_date_toLocalISOString", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could add "ifndef":"SAVE_ON_FLASH"
to try and save a few bytes on micro:bit here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Hi! This looks really good, thanks! I've just enabled the CI check, and there do seem to be some issues though:
But thanks - this looks really neat. It'll be a great addition. |
Yes - that should fix the problem
I'm also surprised at the 1400 bytes this takes. If it fails again then I guess micro:bit will have to do without DST.
I've had horrible problems with tabs. |
I've done a bit of refactoring so that the code should take a bit less space. Expect another commit probably later today. |
Excellent - thanks! |
1 similar comment
Excellent - thanks! |
I think that's about as good as I can make the code. I've implemented the ESPR_NO_DAYLIGHT_SAVING for microbit1, but I can't get it to compile for that platform! Could you review and see if I did ESPR_NO_DAYLIGHT_SAVING correctly? Or am I doing something wrong with my attempts to compile the microbit1 version? |
Great - thanks! I'll take a look tomorrow and will see about merging |
This looks great to me - the microbit build seems to work fine as well. Merging now - Thanks for this, and for making those tweaks! |
Curious. I still cannot get the microbit1 build to work - which means that it's possible the microbit1 could actually support DST. Worth trying it out? |
OK - figured out why I wasn't able to compile for microbit1 - I didn't have RELEASE=1 in my makefile. The microbit1 cannot run the DST code for want of a measly 332 bytes. So unless I can think of some way of squeezing out another 332 bytes we can call this project done. |
Well yes, but even if you squeezed it down 332 bytes and got it to compile, it's means that the very next improvement (even if it's a bugfix) will likely break the compile. microbit 1 is super limited and we leave a lot of stuff out of it already - so I think not having it built in is the right thing to do anyway. |
Hi! I know this is a while ago, but a segfault issue was just reported at #2456 Some weirdness can be reproduced just by doing It's giving negative values for days/months in some cases if the date is before 1970. Before your changes went in, this worked fine.
It seemed you had a really thorough write-up in https://github.com/deirdreobyrne/CalendarAndDST so I thought this was worth asking you about first |
Eeeeep - my code is only supposed to be used with the Gregorian calendar
(i.e. post-1582, or post-1752 in the UK, US and elsewhere).
And yes I can see how it might have a problem pre-1970, as I coded it with
the idea that Date() starts in 1970.
Which is the most important thing to fix? That it doesn't segfault? That it
is consistent going between millis and Dates? Or that it gives what could
be considered the "right" answer (which would be for example to use
Gregorian after 1582 and Julian before)?
D.
…On Fri, 26 Jan 2024 at 14:52, Gordon Williams ***@***.***> wrote:
Hi! I know this is a while ago, but a segfault issue was just reported at
#2456 <#2456>
Some weirdness can be reproduced just by doing d = new Date(-12,8) which
seems valid, and this looks like it's down to your replacement
getDateFromDayNumber which comes from
https://github.com/deirdreobyrne/CalendarAndDST
It's giving negative values for days/months in some cases if the date is
before 1970.
Before your changes went in, this worked fine.
// before
>d = new Date(-12,8)
=Date: Tue Aug 31 -12 00:00:00 GMT+0000
// after
>d = new Date(-12,8).ms
=-62524915200000
>d = new Date(-12,8)
=Date: Wed h -29 -11 00:00:00 GMT+0000
It seemed you had a really thorough write-up in
https://github.com/deirdreobyrne/CalendarAndDST so I thought this was
worth asking you about first
—
Reply to this email directly, view it on GitHub
<#2230 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AGZJOLEXREUHFVGMCH3QIATYQO7KFAVCNFSM52TSFGA2U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TCOJRGIYTSMJSGIZQ>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Thanks! Well, from my point of view:
I don't think the Date<->millis thing matters pre-1582, but it'd be nice if within reason you could add one day's worth of milliseconds and get to the next day. |
I believe I have a bugfix in my github account.
The good news is that I believe it will be good for over 71,000 years.
Though in the very distant past and future you might find yourself unable
to add or subtract a day, due to the precision of floating point, and you
may also have an "incomplete" calendar.
HOWEVER in astronomy (which is one of my hobbies) the convention is to use
the Gregorian calendar as far back as the Gregorian reform in 1582, and the
Julian calendar before that. (And it is also standard practice to have no
year zero). My code breaks these two conventions.
The solutions I see are -
1) Break the conventions
2) Develop code for the Julian calendar, and code to switch between Julian
and Gregorian on the appropriate date in 1582. Whereas different countries
implemented the switch on different dates, the convention is to use the
1582 date.
3) Throw some sort of exception for dates before that date in 1582 (if I'm
reading your code correctly it's fairly easy to throw exceptions?)
Solution 3 is the most technically accurate easy solution, and solution 2
is a reasonably technically accurate difficult solution. I don't like the
current state of affairs.
What do you think?
D.
…On Fri, 26 Jan 2024 at 15:13, Gordon Williams ***@***.***> wrote:
Thanks! Well, from my point of view:
- It shouldn't ever segfault (eg month always 0..11, day always 1..31)
- pre-1970 at minimum (ideally 1582) I don't really care, if you do new
Date(-1000,7,1) you should expect it'll say
=Date: ... Jul 1 -1000 00:00:00 GMT+0000 in return. Right now it says Date:
Fri ength -27 -999 00:00:00 GMT+0000
I don't think the Date<->millis thing matters pre-1582, but it'd be nice
if within reason you could add one day's worth of milliseconds and get to
the next day.
—
Reply to this email directly, view it on GitHub
<#2230 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AGZJOLFXEB6YHNGEDA3EJEDYQPB3FAVCNFSM52TSFGA2U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TCOJRGIZDEOBYHAYQ>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Sorry for the delayed response - what you've managed with #2459 looks great though! Having as wider range as possible using Gregorian and throwing an exception outside of that seems great |
Adds
E.setDST()
, which gives Espruino rules for determining when daylight savings time starts and ends. Note thatE.setTimeZone()
will have no effect when daylight savings time rules are in effect. (I note that Gadgetbridge sets the time zone, so by disabling the effectiveness ofE.setTimeZone()
we prevent clashes between Gadgetbridge and this DST code when DST changes).Note that one of the tests in
tests/test_date.js
was actually wrong. It was assuming GMT, when the timezone was explicitly set withE.setTimeZone(2)
.DST checks have been added to
tests/test_date.js
, and all of them are now passing.