iCalendar durations where the duration's date portion ends inside a DST discontinuity - icalendar

RFC 5545 and other standards like JSCalendar define a P1DT12H duration as one nominal day plus 12 exact hours. Normally this will be 36 real-world ("exact" or "accurate") hours, but:
If a Spring DST transition happens during the "one nominal day" part of that duration, then the accurate duration will be only 35 hours.
If a Fall DST transition happens during the "one nominal day" part, then the accurate duration will be 37 hours.
But what if the starting date/time is exactly one nominal day before a discontinuous period? For example, a P1DT12H duration added to 2020-03-07T02:30 in America/Los_Angeles where DST starts at 2020-03-08T02:00. In that case, what should be the calculated local time at the end of that duration?
Is it 2020-03-08T14:30? 2020-03-08T13:30? 2020-03-08T15:30? Something else? Also: why?
The problem is that the naive way of calculating the exact duration would be to add the date portion of the duration using nominal units, then convert that intermediate result to UTC and add the time portion of the duration using exact time. But that intermediate result is an invalid nominal time that's skipped, then the local time of that intermediate value is 2020-03-08T03:30 (3:30AM, not 2:30AM) because RFC 5545 says:
If the local time described does not occur (when changing from standard to daylight time), the DATE-TIME value is interpreted using the UTC offset before the gap in local times.
So using that interpretation of the spec, the final result after adding the 12-exact-hour time portion should be 2020-03-08T15:30 or 3:30PM.
Is this the "correct" answer according to RFC 5455? If not, what should be the answer and why?
Or is this an ambiguity in the standard and there's no objectively correct answer?

I was hoping someone else would answer. Here is my understanding:
Two concepts here:
Either one has the DTEND and is calculating the DURATION, which as you have established, will vary if there is daylight saving change during the event, OR
one has the duration and is calculating the DTEND. It is best to do that in UTC for safety sake.
RE your question:
But what if the starting date/time is exactly one nominal day before a discontinuous period? In that case, what should be the calculated local time at the end of that duration?
For calculating DTEND, nominal day at same time takes us to invalid time. If one uses UTC to calc that nominal day, one gets 3.30 am. The spec says:
In the case of discontinuities in the time scale, such as the change
from standard time to daylight time and back, the computation of the
exact duration requires the subtraction or addition of the change of
duration of the discontinuity.
I understand this to mean yes, when working out the CALCULATED duration (ie where you have DTSTART and DTEND) will vary depending in the events point in the calendar, as you have noted.
RE your question
But that intermediate result is an invalid nominal time that's skipped, then the local time of that intermediate value is 2020-03-08T03:30 (3:30AM, not 2:30AM...."
Yes, however in calculating further I think you went wrong adding the 12H to the local time. Spec says use the earlier UTC offset, which I take to mean use that to get UTC time, use UTC for the calcs, then convert back.
If the local time described does not occur (when changing from
standard to daylight time), the DATE-TIME value is interpreted using
the UTC offset before the gap in local times.
Note this is the UTC offset. So one nominal day takes us to 2.30am which does not 'exist' in LA on 8 March, so we use the UTC offset before the time gap. -8 hours which gives us UTC=10h30.
Plus 12H gives us UTC 22H30.
If we stay with the -8 offset for calculation purposes, we get local time 14:30.
*It is not 100% spelled out in the specification that this is it. More worked examples to confirm would be good.
Advice I have seen elsewhere is to store times in UTC time, do the calcs in UTC time, then for display, calculate local time.*
RE:
Is it 2020-03-08T14:30?
Is this the "correct" answer according to RFC 5455? If not, what should be the answer and why?
I understand it to be 14H30. I cross checked using PHP, with calcs in LosAngeles and in UTC time before DST & during DST, using both datetime->add https://www.php.net/manual/en/datetime.add.php and https://www.php.net/manual/en/datetime.modify.php and consistently got that answer.
I think correct is 2020-03-08T14:30 because if one uses the UTC offset as specified and calcs in UTC, that is what one gets.
PHP Workings
add a nominal day P01D
Before DST:
2020-03-06T02:30:00-08:00
2020-03-07T02:30:00-08:00 with modify
2020-03-07T02:30:00-08:00 add date interval
Over DST:
2020-03-07T02:30:00-08:00
2020-03-08T03:30:00-07:00 with modify
2020-03-08T03:30:00-07:00 add date interval
add a nominal day plus 12 H ie: P01DT12H
Before DST:
2020-03-06T02:30:00-08:00
2020-03-07T14:30:00-08:00 add date interval
Over DST:
2020-03-07T02:30:00-08:00
2020-03-08T14:30:00-07:00 with modify
2020-03-08T14:30:00-07:00 add date interval
For checking offset: https://www.timeanddate.com/worldclock/meetingtime.html?day=8&month=3&year=2020&p1=137&iv=0

Related

How To Get Timezone Of Date In Swift

I only want to get the current date object's timezone. The Date class in Swift does not have a way to do so. I have seen ways to convert from one timezone to another. But no way to do so extracting the timezone from a date object.
Why is that?
Is there a way to do so? Thoughts on how? Thanks
Dates don’t have time zones. They’re simply a point in time.
E.g., the moment in which Neil Armstrong stepped foot on the moon. You could describe that moment in UTC, or EST, or any other TZ (or even in other calendar systems), but they’re all referring to the same moment. That would be modelled by a singular date object.
By another analogy, an object has a width, but it doesn't know its unit. Its width can be measured in centimetres, inches, plank lengths or light years. These are all abstractions we put on top of the concept of distance, and they all describe the same thing.
Internally, they’re just a Double that counts the number of secs since the reference date. Clearly, there's no timezone there.
Any time zones you see relating to dates are just an interpretive layer on top of that (e.g. print will call .description, which will format it to your local tz for your convenience.).

How does Unix Epoch time behave on a leap smeared clock?

Consider a machine whose time is smeared during a leap second with a noon-to-noon linear smear.
I'm wondering how the system clock provides accurate Epoch time during the smear period.
Example:
The leap second is scheduled at 31st dec of 2016.
On the machine, a Unix timestamp at 11:59:00 on 31st of December is 1483185540
At noon the smearing starts, which means the local clock of the system at 1:30 pm is already a few microseconds behind TAI and UTC. The Epoch timestamp should be 1483191000 (exactly 1 hour 31 minutes later), which is not accurate to TAI/UTC anymore since Epoch doesn't respect leap seconds
At 12pm UTC adds an extra second: 11:59:60 pm, the local smeared clock should continue normally
Till, at noon 1st of January global UTC and local UTC sync up again, the local Epoch clock is now an entire second behind global Epoch/TAI
How is this inaccuracy resolved? Does the local Epoch time skip a second once the system knows a leap second happened? Or how is this issue handled?
Does it depend on the implementation of the clock used to calculate the time? If so, how does GNU's coreutils date handle this?
The inaccuracy is not resolved. The Unix Time remains a count of seconds since 1970-01-01 00:00:00 UTC excluding the inserted leap seconds. This has the benefit of making the count of seconds easy to convert to {year, month, day, hour, minute, second} form.
It has the problem that the subtraction of two Unix Time time points that straddle a leap second insertion will result in a time duration that is one second less than reality.

PostgreSQL: Calculate elapsed hours across time change

How can I calculate the number of hours between two times, taking into account the change from standard to daylight savings time between them?
I need to determine which crew is working in my customer's plant. There are four possibilities, changing in a known order from one to the next every four days, so the crew pattern recurs every 16 days. I had planned to store a reference time in my database. To calculate the crew, I would calculate the elapsed hours between the reference time and the current time, modulo it by 384, and use crew A if the result is below 96, crew B for 96-192, and so on.
I am pretty sure that in the spring, when an hour is repeated at the time change, the crew shift is 13 hours long, and in the fall, the crew shift is only 11 hours long. My scheme, at least if it relied on timestamp with time zone objects, would be wrong for an hour every shift for half the year.
Thank you.

getting current GMT in matlab

How can I get the current date and time in GMT from Matlab if it is connected to Internet. I want to make a world clock which calculates time by adding time offset to current GMT.
I believe you can do it without the internet. You can call
time_ms_UTC= java.lang.System.currentTimeMillis;
for the time in milliseconds. You can covert that to a more readable time and use MATLAB's tzoffset to change timezone to GMT.
Disclaimer: I believe this will not give you the international, atomic clock GMT, but local time. I'll leave the answer here for now.
Credit: http://uk.mathworks.com/matlabcentral/newsreader/view_thread/251275

How to convert month to other duration measurement types?

For some duration-related calculations I need to convert values measured in "months" to other formats, such as years, days, or hours.
For example, what is the proper way to measure a month in terms of days? is it 30 days? or 30.4375 days? (365.25 / 12) and which format would be useful in which cases?
If you have any information on the casual/business use cases for such conversions it would be helpful too.
Unfortunately, there's really no single generally valid answer to your question.
If this is for business use, first check whether there are any existing relevant standards or business practices that define what a "month" means in your business context. If yes, you should follow that definition as closely as possible, however silly or awkward it may seem.
For casual use, the simplest solution is probably to pick any widely use date manipulation library and do whatever it does. The default behavior may not be perfect, but it's probably at least close to a fairly sensible compromise of the many contradictory expectations that users of such a library may have.
OK, but what if you insist on rolling your own solution? In that case, the first choice you should make is how you want to represent date / time values. There are at least two common choices:
The first option is to store dates / times using a simple linear count of fixed time units from a given epoch, such as Julian days or Unix timestamps. This provides a simple and compact date/time representation, makes comparing timestamps and simple date/time arithmetic (like adding n seconds to a time value) easy, and ensures that any time value corresponds to a (more or less) unique and well defined point in time.
The downside, as you've noticed, is that arithmetic using "fuzzy" time units like months or years gets difficult: you can define a year as 365.25 days (or as 365.2425 days, to take into account that only 97 out of every 400 years are leap years in the Gregorian calendar) and a month as 1/12 years, but this will cause adding a year to a date-time value to also shift the time of day by (about) 6 hours, which may be unexpected.
This approach also doesn't let you easily represent "floating" time value, like times of day without a specified date and time zone. (You can sort of deal with floating time zones by doing your time math in UTC and just pretending that it's in your local time zone, but this can cause weird stuff to happen around DST changeovers.) Conversely, it can also cause difficulties if you need to represent imprecise date/time values, such as dates without a time component.
In particular, if you choose the "natural" representation, where imprecise datetimes are represented by their starting point, so that e.g. an unspecified time of day defaults to 00:00:00.0, then anything that causes the time part to be reduced by even a fraction of a second — like, say, shifting to a later time zone, or subtracting a fuzzy time unit that is not an integral number of days — will flip the date part to the previous day. For example, with this representation, subtracting one year (= 265.2425 days) from January 1, 2014 will yield a date in 2012 (specifically, December 31, 2012, 17:56:32)!
You can avoid some of these issues by representing imprecise date/time values by their midpoints instead, so that e.g. the date 2014 is treated as shorthand for June 2, 2014, 12:00:00. What you lose, with this representation, is the ability to build datetimes just by adding up components: with this representation, 2014 + 5 months + 3 days isn't anywhere near May 3, 2014.
Also, just when you think you've at least got simple non-fuzzy time arithmetic unambiguously sorted out, someone's going to tell you about leap seconds...
The alternative approach is to store datetime values in decomposed year / month / day / hour / minute / second / etc. format. With this presentation, time intervals are also naturally stored in a decomposed format: "one month + 17 days" is, in itself, a valid time interval in such a representation, and need not (and should not) be simplified further.
This has a few obvious advantages:
Fuzzy unit arithmetic is (conceptually) simple: to add one year to a date, just increment the year component by one.
Imprecise date/time values can be naturally represented: for a pure date value, the time-of-day components can simply be left undefined (= e.g. represented by negative values for the undefined components, or simply by having each datetime value store its precision).
You have precise control over when and if rollover occurs: adding a year to a date in 2014 will always yield a date in 2015.
You can also support floating time values, such as times of day without a specified date, or dates of year without a specified year. Floating time zones also become supportable.
That said, there are some disadvantages, too:
Implementing date arithmetic gets more complex, since you have to deal with non-trivial carry/borrow rules. (Quick! What's the date 10,000,000 seconds after May 3, 2014?)
You'll still have ambiguities with month arithmetic: what's the date one month after January 31? And does it depend on whether it's a leap year or not?
You can allow such a format to store "impossible" dates like "February 31", with an optional method to normalize them to, say, February 28 (or 29, for a leap year) later. This has the advantage of preserving (some) arithmetic consistency: it allows (January 31 + 1 month) + 1 month to equal March 31 as expected.
In some ways, though this merely postpones the problem: presumably, January 31 + 24 hours should fall on February 1, but what day and month should January 31 + 1 month + 24 hours fall on? The "obvious" choice would be March 1, but whatever you choose, there will be some sequence of arithmetic operations that will yield inconsistent results.