For example, Foo Holiday is the 3rd Tuesday in March. Bar Holiday is the 7th minute of the 7th hour of the 7th day of the 7th Month.
I have looked at standards like ISO8601 but it seems those are more concerned with explicit points in time.
As AlexApps99 described in their answer,
there is no standard that will cover all holidays.
For example, the start of Ramadan often depends on physically sighting the new moon, so it's impossible to predict the exact date, as cloudy weather might prevent anybody from spotting it in your country for a few days.
However, for many repeating events the follow simpler rules (e.g. Foo & Bar Holiday in your question), there is
iCalendar's RRULE (Recurrence Rule),
which is a standard for creating repeating patterns for recurring events.
Many calendar apps will have a GUI for creating RRULE.
RRULE is documented in
RFC 5545 Section 3.8.5.3.
For example, an event for U.S. Presidential Election day would be:
Every 4 years, the first Tuesday after a Monday in November, forever (U.S. Presidential Election day):
DTSTART;TZID=America/New_York:19961105T090000
RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8
Example taken from RFC 5545 Section 3.8.5.3 Page 129
Foo Holiday (3rd Tuesday in March) could be described with:
RRULE;FREQ=YEARLY;BYMONTH=3;BYDAY=TU;BYMONTHDAY=15,16,17,18,19,20,21
Bar Holiday could be described with (7th minute of the 7th hour of the 7th day of the 7th Month) could be described with:
RRULE;FREQ=YEARLY;BYMONTH=7;BYMONTHDAY==7;BYHOUR=7;BYMINUTE=7
Unfortunately, the iCalendar RRULE spec can't can't handle more complicated rules.
Easter can't be done, (although https://github.com/sappjw/calendars contains Easter RRULEs accurate for
1900-2099, and the Python dateutil library's RRULE has an unofficial extension called BYEASTER, but even then, it only supports Western Easter).
Non-Gregorian calendars are also not supported, however, there is a
draft spec RFC7529 that adds
RRULE support for additional calendars, which would allow you to describe
Chinese New Year using the following syntax:
DTSTART;VALUE=DATE:20130210
RRULE:RSCALE=CHINESE;FREQ=YEARLY
SUMMARY:Chinese New Year
These define a recurring event for the Chinese New Year, with the
first instance being the one in Gregorian year 2013.
Example taken from RFC7529#Section 4.3.1
There's no standard way to represent holidays, because holidays are pretty hard to keep track of. Each country has their own set of holidays, and there are different definitions for what is considered a holiday (public holidays, school holidays, religious holidays, international hotdog day etc).
On top of that, the days that holidays lie on is pretty hard to predict. Many holidays celebrating events on the non-Gregorian calendar, such as Easter, will be on a different date each year, and others based on external events can be unpredictable into the future.
Many holidays are not just "days", but a range multiple days, or specific hours of a day, and you can't forget that these intervals have timezones attached too (and will be different in different countries)
With all this complexity, you'll need to create your own way to represent these holidays, probably ignoring some of the complexity you don't need to handle.
If you're sharing this data, a standard format such as iCalendar would be ideal, and you could store custom properties of the holidays in extension fields (starting with X-).
If you're just storing this data internally, you're better off making your own structure to store whatever you need, perhaps using ISO8601 to store the intervals.
Related
I'm trying to get Dialogflow to report sales in different time periods. When I ask things like
what's the sale last month
what's the sale in march 2011
They work fine. However, if I didn't specify "last" or year, Dialogflow always think I'm asking about the upcoming period (which I guess works great for restaurant booking, etc.). For example, "what was our sale in april" would guess that I mean April of next year.
Should I write a fulfillment to deal with this or is there a way to specify only historical periods only?
Another related question is it has trouble understanding notations like 2010q1 or q2/2015 which is quite common in economics and finance. "q1/2000" would extract only q1 (correctly, but with the upcoming q1). "2000q1" wouldn't be recognized at all.
Thanks!
I'm developing some software which interfaces with the Google Calendar API, and one feature my users will be able to take advantage of is setting multiple event times for a single "class" (i.e. the class is 2-5 on some days and 3-6 on others).
Is it possible for a recurrence rule to specify a different time for different days, allowing me to create one repeating event instead of multiple?
Thank you!
Is it possible for a recurrence rule to specify a different time for different days, allowing me to create one repeating event instead of multiple?
No, not really, but you can achieve this result with other methods.
If there is a pattern, you can combine multiple RRULE. For example one repeat every other days starting Monday at 2, the second one repeat every other days starting Tuesday at 3. So the combined result will be Mon at 2, Tue at 3, Wed at 2, and so on. Though note that according to the RFC you SHOULD NOT define more than one RRULE (see
https://www.rfc-editor.org/rfc/rfc5545#section-3.8.5.3)
it SHOULD NOT be specified more than once.
The recurrence set generated with multiple "RRULE" properties is
undefined.
So the behavior depends on the actual implementation and I do not know about Google Calendar API. Most libraries I know of do support multiple RRULE though, so you should give it a try.
Again, if there is a pattern, you can also use BYSETPOS. It's a bit complicated to wrap your head around this one, but basically you need to generate a set of occurrences (for example, over a week) and then cherry pick the ones that are valid. Try something like this (multi-lines for clarity):
DTSTART=20160711T140000
FREQ=WEEKLY
BYDAY=MO,TU,WE,TH,FR
BYHOUR=14,15
BYSETPOS=1,4,5,8,9
This will alternate Monday at 2, Tuesday at 3, Wednesday at 2, and so on. Again, you need a clear repetitive pattern for this one to work.
If there is no pattern and you just want to have some days with a different time, combine your RRULE with RDATE and EXDATE to add or remove special occurrences.
You can use multiple RRULE on Google Calendar but I do not recommend it. See the v3 API documentation -- recurrence[]. Pass an array of strings.
While Google Calendar will respect multiple RRULE, Apple Calendar currently will only use one. This means that anyone uses Apple Calendar on their laptop/phone (synced from Google Calendar) will not see all recurrences.
Also, even though Google Calendar will repeat the event correctly, the written description of repeats used in the UI only describes one RRULE.
eg. "Weekly on Thursday, until May 15, 2021", not "Weekly on Tuesday & Thursday, until May 15, 2021"
Is it possible to specify an event to occur on the 1st weekend day of multiple months every 2 years in a single RRULE? Using February and September as a test case, my first thought was:
FREQ=YEARLY;DTSTART=20140320T070000Z;INTERVAL=2;BYSETPOS=1;BYMONTH=2,9;BYDAY=SA,SU
but BYSETPOS reduces the set down to February only. I thought changing the freq to monthly would do the trick after I posted here, but applying an interval of 2 for every other year messes things up because the interval is applied to a monthly freq instead of a yearly freq.
I made this a new question because I did not include interval in my original question.
I think splitting this into multiple rrules would work, but it would greatly increase the complexity of this area of my app so I was hoping for a single rrule with a yearly freq.
Thanks!
FWIW, and since you mention it as a potential workaround, RFC5545 has removed the ability to have multiple RRULE property in a single VEVENT/VTODO (https://www.rfc-editor.org/rfc/rfc5545#section-3.6.1). It was there in RFC2445.
Then, unless someone finds a very elegant and simple solution, you may be left with something that is so convoluted that most clients will barf on it (don't know how interoperability is important to you).
This leaves you with 2 choices I think:
either use 2 different events (maybe linked with a RELATED-TO property)
or, if you can bound the event to a certain number of instances, represent it as a set of RDATE (or RRULE + RDATE, or RRULE + EXDATE, etc...).
Adding BYSETPOS like this may work as you intend:
FREQ=YEARLY;INTERVAL=2;BYMONTH=2,9;BYDAY=+1SA,+1SU;BYSETPOS=1,3
what you could try is to take advantage of the fact that bysetpos allows you to select within the year the selected instances of your rule, then you could limit the number of instances to the first week of the month (by setting the days of the month to the first 6 ones) to avoid the cases where month have more or less weeks, which then allows you to select the first and third instance in your year.
Which then gives:
DTSTART:20140320T060000Z
FREQ=YEARLY;INTERVAL=2;WKST=MO;BYSETPOS=1,3;BYMONTH=2,9;BYMONTHDAY=1,2,3,4,5,6,7;BYDAY=SA,SU
which will be:
Sat 2014/Sept/6
Sat 2016/Feb/6
Sat 2016/Sep/3
...
Sun 2024/Sep/1
this was verified with dateutil-python and http://jkbr.github.io/,
Is there a way to express the following in iCalendar? (possibly using RRULEs?)
Between 9am and 5pm every day except Sundays when it is between 10am and 4pm.
Can I create multiple RRULEs? Which ones have precedence?
iCalendar does not have a notion of events with a hole in the middle of the duration. So even without talking about recurring event, you can not create with a single event something like from 9AM to 10AM and from 4PM to 5 PM
As a consequence, you need to actually create 3 events:
DTSTART:2013xxxxT090000
DURATION:PT1H
RRULE:FREQ=DAILY
DTSTART:2013xxxxT100000
DURATION:PT6H
RRULE:FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR,SA
DTSTART:2013xxxxT160000
DURATION:PT1H
RRULE:FREQ=DAILY
As far as having multiple RRULE, this was supported in RFC2445 but it has been deprecated in RFC5545 (just like EXRULE) due to lack of support and complexity.
I need to do some date + time stuff that is not covered well by NSDate on the iPhone. I wonder if there is a library that has more sophisticated functionality regarding dates and time on a international level.
What I want to do is advanced date + time mathemathics. I need to:
convert between different calendar types (Gregorian <> Jewish <> Muslimish <> others)
convert times between different time zones (i.e. I have a swedish time and want to know what time is it in chicago)
add microseconds, seconds, minutes, hours, days, weeks, months, years to a date and find out what exact date+time it is then
find out how many microseconds, seconds, minutes, hours, days, weeks, months and years are between two given dates
draw calendars, so I need data about how many days a specific month has in a specific year
use case, for example: I fly from paris to chicago, and at 10:00 'clock in paris I only know the flight will take 10 hours. So I need to convert time zones and all this stuff to calculate what time I'll arrive in chicago. And then all this ugly summer and winter time stuff where they add or reduce one hour at some point in the year, and I think every country does that to their own liking, some may even fake the time way more than that adding a whole day to a year just to have more time. Don't know. Maybe there's a lib that protects me from all this complexity.
Basically what I want to do is a kind of world calendar but with some special features.
It's in the Date and time programming guide.
Convert from one calender to another
Convert between time zones
Calendrical calculations
etc...
NSCalendar + NSDateComponents?
However, like Peter Hosey said, it's hard to know without knowing what it is you want to do.
For people coming here looking for a lib, try Erica Saduns NSDate-Extensions. It doesn't cover everything you might want, but at least you won't have to do the basic stuff yourself.