Why are repeated days incorrect with this RRULE? - calendar

This should be a 2 hour 50 minute event starting at 5pm PST on a thursday evening repeating weekly. When imported into google calendar or Evolution, the first occurrence is correct, but subsequent weeks have the event on Wednesdays.
DTSTART:20170908T000000Z
DTEND:20170908T025000Z
RRULE:FREQ=WEEKLY;UNTIL=20171201T080000Z;BYDAY=TH
Other events that my application generate occur on multiple days i.e. BYDAY=TH,TU so simply removing the BYDAY is not a solution for my problem.

You are mixing up the timezone of the event and the display timezone. As far as recurrence calculation goes, the only thing that counts is the timezone that you declare in the VEVENT. Here you are using UTC. So:
The first instance is on the 20170908 which is a Friday. From there, you ask for a recurrence every thursday. The next thursday after 20170908 is 20170914, so the next instance starts on 20170914T000000Z.
When viewed with a display timezone of PST, this event has indeed its first instance on Thursday evening. But the second instance, as calculated above, is on a Thursday UTC time, so on a Wednesday PST time.
Besides this particular issue, you also need to worry about daylight saving changes. If your event is really taking place in PST timezone, the event, as expressed above will see its time change in November, after the DST transition takes place.
Hence it is almost never a good idea to express a recurring event by using UTC (Zulu) time.
You should have your event expressed in local time with timezone, i.e. use:
DTSTART;TZID="America/Los_Angeles":20170907T170000

Related

How to create an iCalender event that repeats very irregulary?

Background: where I park my car, during the winter it is cleaning day once a week (=parking is not allowed) so I have to move the car before that to avoid getting a ticket. I want to create an iCal reminder about that but the pattern is very complicated.
The season starts Nov 1 and ends May 15.
Only weekdays are cleaning nights.
There are two repeating patterns, yearly (Nov to May) and every 4/6 days (see the examples below for details)
Examples:
I am parked on a street where Wednesday is the cleaning day (i.e., "Wednesday street") so Tuesday evening I move the car to a street that just was cleaned (i.e., a "Tuesday street"). Every week the day I have to move the car is moved forward one day. The repeating pattern is "every 6th day".
However, if I have parked on a Monday street, the situation is different - then I want to move the car on the Friday, not the Sunday. Suddenly the repeating pattern is "every 4th day".
I have read this question Can iCal schedule an event for the first weekday after BYMONTHDAY if BYMONTHDAY is a weekend? and have figured out a couple things:
I can set BYMONTH=11,12,1,2,3,4,5 to limit it to Nov to May.
BYDAY=MO,TU,WE,TH,FR limits it to weekdays
but after that I am stuck. I have been playing around at http://recurrence-expansion-service.appspot.com/ with different combinations but so far without success.
How do I limit it to mid-May?
How do I write a rule that "skips" the weekends when I have parked on a Monday street?
How do I achieve two repeating patterns (a yearly pattern - Nov to May - and a 4/6 day pattern)?

How to control the time of day in React Suite's DateRangePicker?

I cannot for the life of me figure out how to default the time of day in DateRangePicker to 00:00:00 for start date and 23:59:59 for end date.
The time of day simply defaults to the current time on the computer, which, frankly, is rarely what the requirements for a date range are. So It's hard for me to imagine there is no way to do what I'm trying to do. Check out the screenshot:
Here I picked the date range of Apr 22 to May 4. But notice the time of day. In order to set those to 00:00:00 and 23:59:59 respectively, I have to click on those times and scroll around to pick specific time of day, which is super annoying to do every time.
The documentation says nothing about the time. Also their GitHub issues page does not address this. What am I missing here. It seems like such an obvious oversight to not allow you to set a default time of day.
You can set the default time on the calendar via defaultCalendarValue.
<DateRangePicker
format="yyyy-MM-dd HH:mm:ss"
defaultCalendarValue={[new Date('2022-02-01 00:00:00'), new Date('2022-03-01 23:59:59')]}
/>
This has also been updated in the example on the rsuite official website.
https://rsuitejs.com/components/date-range-picker/#date-time-or-time

Event every 5th day of mont (or 4th/3rd if it's weekend or holiday) using iCal

In Brazil my payday happen on every 5th day of month.
But if the 5th day is a saturday/sunday, then the payment will happen on the 4th day.
Same if 4th is saturday/sunday: then the payment will happen on 3rd day. And so on.
Is there any way to create a event that will work with Google Calendar and iCal?
You can achieve that with iCalendar, at least as far as it concerns weekends.
Consider the following rule:
DTSTART;TZID=US-Eastern:20160505T000000
RRULE:FREQ=MONTHLY;BYMONTHDAY=1,2,3,4,5;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1
The rule is evaluated as follows:
FREQ=MONTHLY;BYMONTHDAY=1,2,3,4,5: expand to the 1st, 2nd, 3rd, 4th and 5th day of each month
BYDAY=MO,TU,WE,TH,FR: filter by week day, retain only work days/remove weekend days
BYSETPOS=-1: retain only the last day of the set
You can verify the result at http://recurrence-expansion-service.appspot.com/
Here are the first 100 instances.
It's not possible to achieve that for holidays though.
Update:
It's actually sufficient to specify
RRULE:FREQ=MONTHLY;BYMONTHDAY=3,4,5;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1
Since the weekend is at most 2 days long, payday must fall on one of the 3rd, 4th or 5th day of the month. Again, this does not take holidays into account.
Holidays always need special consideration. Not only does RRULE not support this kind of logic for arbitrary days, sometimes it's difficult or even impossible to express holidays by an RRULE themselves. In some countries certain holidays are always on a specific day, except when the days falls on a weekend, in which case the holiday is on the Friday before or the Monday after the weekend. Or consider the Easter date and holidays relative to the Easter date, they can't be expressed by an RRULE at all.
Not to forget that some holidays may change every now and then (like "King's days" or "Queen's days" in certain countries).
The best you can do is to manage these manually and add an RDATE and an EXDATE if payday would fall on a holiday according to the RRULE above.

Getting a local date/time for a specific timezone in SQL Server

Using SQL Server 2008+. SQLCLR is not an option.
I have a situation where I have data all stored in UTC. I need to do a comparison against that data by determining what a certain local time, let's say 8am, is in UTC. The timezone for the local time will vary on a row by row basis. (The timezone for each row is stored, so that's not an issue.) That certain local time has no date associated with it. It's always just "8am".
I have timezone data in the database, and this tells me the base UTC offset as well if the timezone follows daylight savings time.
But now I'm kind of stuck.
My problem is that in order to do a daylight savings time adjustment, I need to know if the current date/time in a particular timezone falls within certain ranges, but I can only convert to the appropriate local time to do that check if I know if it's daylight savings! In other words, how can I check to see if it's daylight savings unless I know whether a UTC offset is off due to daylight savings?
It's a chicken and egg problem.
It seems to me that the only solution is to be able to have a table that calculates daylight-savings aware offsets on a per-timezone basis.
Ideas?
You do have an ambiguity problem here, but it's not a chicken and egg issue.
The piece of information you are missing is, "what defines a day?" I know, it sounds crazy, but a "day" is not a universal concept. It's a local one.
For just a minute, put aside issues of time zones, DST and UTC. If I ask you, "How many hours are we apart from 8 AM right now?" You could give me two different answers. It's 7PM right now, so you might say "11 hours" - since that's how much time we are from 8 AM today. But I could also have said "13 hours" - since that's how much time we are from 8 AM tomorrow. Now in this very simplistic sample, you could disambiguate in one of two different ways. You might say "the last 8AM" or "the next 8AM". Or you might say "whichever happened today."
Now go back to the concept of UTC. What is a "UTC day?" Well, we know it's 24 hours, since UTC doesn't follow any daylight savings time. But saying that it runs "midnight to midnight UTC", isn't a very meaningful measure. Sure, there are some places that use this definition (for example, StackOverflow's stats engine). But for most people, we think of "today" in our own local time.
So I can't really say "whichever 8AM happened today". The only date measurement you have is a UTC date. You won't know which local date you should be looking at. Let's take a real example:
I live in Phoenix, Arizona, so my time zone offset is UTC-7. We don't have DST here.
It is currently June 14th 2013, 7 PM local time.
So that's June 15th 2013, 2 AM UTC.
Now I record that time in the database, and later I ask:
"How far away are we from 8 AM Arizona time?"
With the information I have, I don't know if I should be looking for 8 AM on June 14th, or 8 AM on June 15th. Only the latter falls on the same UTC date, but I certainly could be interested in either one of them.
If you can decide in your business logic that you want the last time, or the next time, then you can resolve this. Simply convert the UTC datetime to the local time zone. Then roll forward or backward to the desired time. If your time zone has DST and you cross a transition date along the way, you can adjust for that.
You could also pick the nearest time of the two, but of course that all depends on your business logic.
Another approach would be to figure out which local today you are in, using the UTC time you are comparing. So in my example above, Arizona's local June 14th runs from June 13th 17:00 UTC to June 14th 17:00 UTC.
So to summarize, you wanted to know "Is 8 AM in DST surrounding this UTC datetime?", and you can't answer that without more information, either the date of the 8AM, or some logical relationship to follow, of which there are several options available. Pick a strategy that works for your needs.
UPDATE
You asked in comments:
How can I know if right now in UTC is in dst in X time zone so I can adjust accordingly?
This is where the datetimeoffset type can be helpful. You don't just want to track "is DST in effect", you want to track the precise offset for the target time zone, including any DST that might be in effect. The difference is subtle, but it comes down to tracking a full offset rather than just a boolean yes/no.
So, let's pretend I live in New York City. Checking this site, we know that EDT went into effect on March 10th 2013 at 2AM local time, and it will go back to EST on November 3rd 2013 at 2AM local time.
So we have the following:
UTC Local datetimeofffset
2013-03-10T05:00:00Z 2013-03-10T00:00:00-05:00
2013-03-10T06:00:00Z 2013-03-10T01:00:00-05:00
2013-03-10T07:00:00Z 2013-03-10T03:00:00-04:00 <--- transition
2013-03-10T08:00:00Z 2013-03-10T04:00:00-04:00
...
2013-11-03T04:00:00Z 2013-11-03T00:00:00-04:00
2013-11-03T05:00:00Z 2013-11-03T01:00:00-04:00
2013-11-03T06:00:00Z 2013-11-03T01:00:00-05:00 <--- transition
2013-11-03T07:00:00Z 2013-11-03T02:00:00-05:00
Now notice that if you strip off the offset, you only have a one-way function. In other words, you can always determine the correct local time for the UTC time, but you can't go the other direction unless you know the offset during the fall-back transition (or unless you are willing to live with ambiguity).
So the algorithm for going from UTC to local time should be something like this:
Starting with the UTC datetime: 2013-11-03T05:30:00Z
Apply the standard offset (-5) 2013-11-03T00:30:00-05:00
Apply the daylight offset (-4) 2013-11-03T01:30:00-04:00
Which one is valid according to the time zone rules?
In this case, the daylight offset is valid.
Your time zone data should have this information.
If not, then you need to reconsider the source of your time zone tables.
Let's try it again with the other 1:30 time:
Starting with the UTC datetime: 2013-11-03T06:30:00Z
Apply the standard offset (-5) 2013-11-03T01:30:00-05:00
Apply the daylight offset (-4) 2013-11-03T02:30:00-04:00
Which one is valid according to the time zone rules?
In this case, the standard offset is valid.
How do we know? Because -4 is the daylight offset, and DST is supposed to be over at 2:00 local time. We have 2:30 local time associated with that offset, so only the standard one is valid in this time zone.
So can you convert from UTC to local? Yes. Always.
But you also said that the local value in the other column is just something like 8AM. So if it was 1:30AM, then certainly you would have an ambiguity during the fall-back transition. There is no way to resolve this, other than just picking one.
Sometimes, you might want to just pick one or the other, but sometimes you might want to error. And sometimes you might want to let your user pick which of the two they were interested in. It's not unheard of to see a dialog such as the following:
DAYLIGHT SAVING TIME
We're sorry, but there are two different instances of 1:30 AM on this day.
Which did you mean?
[1:30 AM Eastern Daylight Time] [1:30 AM Eastern Standard Time]
...those are buttons, if you couldn't tell. :)

Storing and searching opening/closing times for stores

I'm writing an application that indexes data for our stores, some of which are open late (8 am - 2 am). We need to be able to search this database quickly -- basically, to run a query to find which stores are open at a given point in time (now, Sunday at 1 am, whatever).
In addition, the open/close times can vary day-by-day -- some stores are closed on Sundays, for example.
The obvious solution to me would be to make a table where I have a row with the store ID, day, open time, and close time. For something like Monday, 8 am - 2 am, that would actually be two rows, one for Monday 0800 - 2400, and one for Tuesday 0000 - 0200.
We have a lot of stores, so the search has to perform well (basically, the data has to be index-friendly), but I'll also have to display this data back out in a human-readable format. With my current solution, that'd look something like this:
Monday: 8:00 - Midnight
Tuesday: Midnight - 2:00 am; 8:00 am - Midnight
I'm just wondering if anybody else has alternative solutions before I jump right to an implementation. Thanks!
When PBS (the US Public Broadcasting System) faced this same problem a couple of years ago, they invented the idea of the "30 hour day" -- Where 00:00 is midnight at the start of the day, 24:00 is midnight at the end of the day, 25:00 is 1am the next day, 30:00 is 6am the next day. That way Mon closing time of 26:00 is 2am Tues morning.
Rather than two records representing a single store's times for a day, it may be more object oriented to think of the "store day" as the object. That way 1 record = 1 store's times for a day. If you want to store the two sets of open/close times, just use four fields in the record instead of two--and adjust your queries appropriately.
Remember that your queries should use a library/api that you write and publish. The library will then deal with the data store and its data layout. No one but your library should be looking at the db directly.
Time zones are very important in this sort of app too. (Hopefully) at some point, the store chain will expand to cover more than one time zone. You'll then need to determine the local time of the query. -- May not the same as the time zone of your server which is handling the queries.
Further thoughts--
I now see that you're standardizing to GMT. Good. You could also use datetime values (vs time values) and standardize to a given week in time. Eg open time is Sun Jan 1, 1995 10am - Mon Jan 2, 1995 2am (using Jan 1, 1995 as a base since it was a Sunday).
Then rationalize your "current time and date" to match the same point in the week of Jan 1, 1995. Then query to find open store days.
HTH,
Larry

Resources