I'm building a backend at the moment which has a number of objects which have associated dates and times, which repeat at a fixed interval, for instance:
Object 1: Repeat Weekly on Tuesdays at 17:00 UTC.
Object 2: Repeat on the first Wednesday of the month at 12:00 UTC.
Object 3: Repeat every other week (fortnightly) on Friday at 13:00 UTC from January 1, 1970.
I'm looking for the best way to represent this interval in a database, short of generating a calendar file with the object's repeating date/time info in it.
Related
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)?
I'm struggling to format a cron schedule for gcp properly and the docs aren't really helping me out.
Cron #1: Run every 50 minutes from 11:00 to 21:00 only on the months from march to october inclusive
schedule: every 50 minutes from 11:00 to 21:00 of mar,apr,may,jun,jul,aug,sep,oct
Cron #2: Run every day at 22:00 only on the months from march to october inclusive
schedule: every day 22:00 of mar,apr,may,jun,jul,aug,sep,oct
Neither of those work, but they were one of my attempts. What am I doing wrong here?
Referring to the Formatting the schedule docs below.
There is no supported syntax for your 1st cron:
specifying minutes in an [INTERVAL_VALUE] is only supported by END-TIME INTERVAL and START-TIME INTERVAL formats, but neither of them allows specifying months in the [INTERVAL_SCOPE].
the only format supporting month specification in [INTERVAL_SCOPE] is CUSTOM INTERVAL, but that only supports day specifications in [INTERVAL_VALUE].
But you can achieve an equivalent functionality by using the finer time specification in cron.yaml and making a check for the remaining conditions inside the cron job itself, doing nothing if the condition is not met. So your 1st cron would be achieved with:
this cron.yaml entry:
schedule: every 50 minutes from 11:00 to 21:00
an additional check for the current month inside the cron job itself, doing nothing (just returning) if the month is Jan, Feb, Nov or Dec.
Your 2nd cron is possible using a CUSTOM INTERVAL, you just need to place the hour at the end of the [INTERVAL_SCOPE]. From the doc:
[INTERVAL_SCOPE]: Specifies a clause that corresponds with the
specified [INTERVAL_VALUE]. Custom intervals can include the of
[MONTH] clause, which specifies a single month in a year, or a
comma-separated list of multiple months. You must also define a
specific time for when you want the job to run, for example: of
[MONTH] [HH:MM].
So your entry would be:
schedule: every day of mar,apr,may,jun,jul,aug,sep,oct 22:00
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
I want the schedule of a cron job to be the las day of every month. I've used this:
<schedule>last day of month 23:59</schedule>
Is it correct?
The easiest way to launch the job at first of month 00:00. You may tweak it to run few hours before setting the <timezone> to the timezone with more positive value than the desired one. If desired timezone is GMT than you may set the timezone of the cron job to Europe/Berlin and the job will be executed last day of the month at 23:00 GMT.
As per the documentation, the format for the Cron Expression for the kind that you are trying to create is:
("every"|ordinal) (days) ["of" (monthspec)] (time)
Where:
ordinal specifies a comma separated list of "1st", "first" and so forth (both forms are ok)
days specifies a comma separated list of days of the week (for example, "mon", "tuesday", with both short and long forms being accepted); "every day" is equivalent to "every mon,tue,wed,thu,fri,sat,sun"
monthspec specifies a comma separated list of month names (for example, "jan", "march", "sep"). If omitted, implies every month. You can also say "month" to mean every month, as in "1,8,15,22 of month 09:00".
time specifies the time of day, as HH:MM in 24 hour time.
I don't think there is a direct expression for what you are trying to do.
You might need to create multiple cron expressions. For e.g. 31 of month 09:00 would address 31st day of all months at 9:00 AM and it should address all months that have 31 days and so on.
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