Supported time periods for building schedules and performing time based calculations.
Time periods are the crux of the Later library and are used to define new schedules. Later comes with a large assortment of time periods and is also fully extensible making it easy to create custom time periods.
While time periods are primarily used by Later to define schedules and calculate occurrences, they are also useful for performing time based calculations. Calculating values such as ISO week number, moving between days of the year, or figuring out how many days are in a month are all possible using the time period interface.
If you don't see the time period that you need for your schedule, Later is fully extensible and it is easy to write your own. See the custom time period at the bottom of this page for an example.
All time periods implement the same public interface for interacting with them:
Seconds in a minute, from 0 to 59.
Using seconds in a schedule:
var sched = {schedules: [{s: [0, 15, 30, 45]}]};
Performing seconds based calculations:
var d = new Date('2013-03-22T10:02:05Z'); later.second.name; --> 'second' later.second.range; --> 1 later.second.val(d); --> 5 later.second.isValid(d, 10); --> false later.second.extent(); --> [0, 59] later.second.start(d); --> 'Fri, 22 Mar 2013 10:02:05 GMT' later.second.end(d); --> 'Fri, 22 Mar 2013 10:02:05 GMT' later.second.next(d, 27); --> 'Fri, 22 Mar 2013 10:02:27 GMT' later.second.prev(d, 27); --> 'Fri, 22 Mar 2013 10:01:27 GMT'
Minutes in an hour, from 0 to 59.
Using minutes in a schedule:
var sched = {schedules: [{m: [0, 15, 30, 45]}]};
Performing minutes based calculations:
var d = new Date('2013-03-22T10:02:05Z'); later.minute.name; --> 'minute' later.minute.range; --> 60 later.minute.val(d); --> 2 later.minute.isValid(d, 2); --> true later.minute.extent(); --> [0, 59] later.minute.start(d); --> 'Fri, 22 Mar 2013 10:02:00 GMT' later.minute.end(d); --> 'Fri, 22 Mar 2013 10:02:59 GMT' later.minute.next(d, 27); --> 'Fri, 22 Mar 2013 10:27:00 GMT' later.minute.prev(d, 27); --> 'Fri, 22 Mar 2013 09:27:59 GMT'
Hours in a day, from 0 to 23.
Using hours in a schedule:
var sched = {schedules: [{h: [0, 5, 12]}]};
Performing hours based calculations:
var d = new Date('2013-03-22T10:02:05Z'); later.hour.name; --> 'hour' later.hour.range; --> 3600 later.hour.val(d); --> 10 later.hour.isValid(d, 2); --> false later.hour.extent(); --> [0, 23] later.hour.start(d); --> 'Fri, 22 Mar 2013 10:00:00 GMT' later.hour.end(d); --> 'Fri, 22 Mar 2013 10:59:59 GMT' later.hour.next(d, 5); --> 'Sat, 23 Mar 2013 05:00:00 GMT' later.hour.prev(d, 21); --> 'Thu, 21 Mar 2013 21:59:59 GMT'
Time of day, represented as seconds since midnight. From 0 to 86399.
Using time in a schedule:
var sched = {schedules: [{t: [6500]}]};
Performing time based calculations:
var d = new Date('2013-03-22T10:02:05Z'); later.time.name; --> 'time' later.time.range; --> 1 later.time.val(d); --> 36125 later.time.isValid(d, 36125); --> true later.time.extent(); --> [0, 86399] later.time.start(d); --> 'Fri, 22 Mar 2013 00:00:00 GMT' later.time.end(d); --> 'Fri, 22 Mar 2013 23:59:59 GMT' later.time.next(d, 60); --> 'Sat, 23 Mar 2013 00:01:00 GMT' later.time.prev(d, 60); --> 'Fri, 22 Mar 2013 00:01:00 GMT'
Days of a month, from 1 to max days in month. Specify 0 for the last day of the month.
Using days in a schedule:
var sched = {schedules: [{D: [0]}]};
Performing day based calculations:
var d = new Date('2013-03-22T10:02:05Z'); later.day.name; --> 'day' later.day.range; --> 86400 later.day.val(d); --> 22 later.day.isValid(d, 3); --> false later.day.extent(d); --> [1, 31] later.day.start(d); --> 'Fri, 22 Mar 2013 00:00:00 GMT' later.day.end(d); --> 'Fri, 22 Mar 2013 23:59:59 GMT' later.day.next(d, 11); --> 'Thu, 11 Apr 2013 00:00:00 GMT' later.day.prev(d, 2); --> 'Sat, 02 Mar 2013 23:59:59 GMT'
Days of a week, from 1 to 7. Specify 0 for the last day of the week (Saturday).
Using days of week in a schedule:
var sched = {schedules: [{dw: [2,3,4,5,6]}]};
Performing day of week based calculations:
var d = new Date('2013-03-22T10:02:05Z'); later.dayOfWeek.name; --> 'day of week' later.dayOfWeek.range; --> 86400 later.dayOfWeek.val(d); --> 6 later.dayOfWeek.isValid(d, 3); --> false later.dayOfWeek.extent(); --> [1, 7] later.dayOfWeek.start(d); --> 'Fri, 22 Mar 2013 00:00:00 GMT' later.dayOfWeek.end(d); --> 'Fri, 22 Mar 2013 23:59:59 GMT' later.dayOfWeek.next(d, 1); --> 'Sun, 24 Mar 2013 00:00:00 GMT' later.dayOfWeek.prev(d, 5); --> 'Thu, 21 Mar 2013 23:59:59 GMT'
The nth day of the week within a month, from 1 to max weeks in a month. Specify 0 for the last day instance. Used together with the day of the week time period to specify things like the 2nd Tuesday or last Friday of a month.
Using days of week count in a schedule:
var sched = {schedules: [{dc: [2]}]};
Performing day of week count based calculations:
var d = new Date('2013-03-22T10:02:05Z'); later.dayOfWeekCount.name; --> 'day of week count' later.dayOfWeekCount.range; --> 604800 later.dayOfWeekCount.val(d); --> 4 later.dayOfWeekCount.isValid(d, 4); --> true later.dayOfWeekCount.extent(d); --> [1, 5] later.dayOfWeekCount.start(d); --> 'Fri, 22 Mar 2013 00:00:00 GMT' later.dayOfWeekCount.end(d); --> 'Thu, 28 Mar 2013 23:59:59 GMT' // zero is special cased and means the last instance of // a day of the week in the month, instead of meaning the // first day of the week with the highest instance count // which would have been Mar 29 with value 5. later.dayOfWeekCount.next(d, 0); --> 'Mon, 25 Mar 2013 00:00:00 GMT' later.dayOfWeekCount.prev(d, 2); --> 'Thu, 14 Mar 2013 23:59:59 GMT'
Days in a year, from 1 to max days in year. Specify 0 for last day of the year.
Using days of year in a schedule:
var sched = {schedules: [{dy: [189, 267]}]};
Performing day of year based calculations:
var d = new Date('2013-03-22T10:02:05Z'); later.dayOfYear.name; --> 'day of year' later.dayOfYear.range; --> 86400 later.dayOfYear.val(d); --> 81 later.dayOfYear.isValid(d, 4); --> false later.dayOfYear.extent(d); --> [1, 365] later.dayOfYear.start(d); --> 'Fri, 22 Mar 2013 00:00:00 GMT' later.dayOfYear.end(d); --> 'Fri, 22 Mar 2013 23:59:59 GMT' later.dayOfYear.next(d, 256); --> 'Fri, 13 Sep 2013 00:00:00 GMT' later.dayOfYear.prev(d, 44); --> 'Wed, 13 Feb 2013 23:59:59 GMT'
Weeks in a month where the 1st of the month is week 1 and following weeks start on Sunday. From 1 to max weeks in the month. Specify 0 for last week of the month.
Using weeks of month in a schedule:
var sched = {schedules: [{wm: [1, 2]}]};
Performing week of month based calculations:
var d = new Date('2013-03-22T10:02:05Z'); later.weekOfMonth.name; --> 'week of month' later.weekOfMonth.range; --> 604800 later.weekOfMonth.val(d); --> 4 later.weekOfMonth.isValid(d, 4); --> true later.weekOfMonth.extent(d); --> [1, 6] later.weekOfMonth.start(d); --> 'Sun, 17 Mar 2013 00:00:00 GMT' later.weekOfMonth.end(d); --> 'Sat, 23 Mar 2013 23:59:59 GMT' later.weekOfMonth.next(d, 1); --> 'Mon, 01 Apr 2013 00:00:00 GMT' later.weekOfMonth.prev(d, 2); --> 'Sat, 09 Mar 2013 23:59:59 GMT'
The ISO 8601 week of the year. From 1 to max ISO week in the year. Specify 0 for last ISO week of the year.
Using weeks of year in a schedule:
var sched = {schedules: [{wy: [13,26,39,0]}]};
Performing week of year based calculations:
var d = new Date('2013-03-22T10:02:05Z'); later.weekOfYear.name; --> 'week of year' later.weekOfYear.range; --> 604800 later.weekOfYear.val(d); --> 12 later.weekOfYear.isValid(d, 21); --> false later.weekOfYear.extent(d); --> [1, 52] later.weekOfYear.start(d); --> 'Mon, 18 Mar 2013 00:00:00 GMT' later.weekOfYear.end(d); --> 'Sun, 24 Mar 2013 23:59:59 GMT' later.weekOfYear.next(d, 47); --> 'Mon, 18 Nov 2013 00:00:00 GMT' later.weekOfYear.prev(d, 52); --> 'Sun, 30 Dec 2012 23:59:59 GMT'
Months of the year, from 1 to 12. Specify 0 for the last month of the year.
Using months in a schedule:
var sched = {schedules: [{M: [3,5,7]}]};
Performing months based calculations:
var d = new Date('2013-03-22T10:02:05Z'); later.month.name; --> 'month' later.month.range; --> 2629740 later.month.val(d); --> 3 later.month.isValid(d, 3); --> true later.month.extent(); --> [1, 12] later.month.start(d); --> 'Fri, 01 Mar 2013 00:00:00 GMT' later.month.end(d); --> 'Sun, 31 Mar 2013 23:59:59 GMT' later.month.next(d, 11); --> 'Fri, 01 Nov 2013 00:00:00 GMT' later.month.prev(d, 2); --> 'Thu, 28 Feb 2013 23:59:59 GMT'
Years, from 1970 to 2099.
Using years in a schedule:
var sched = {schedules: [{Y: [2013, 2014, 2015]}]};
Performing years based calculations:
var d = new Date('2013-03-22T10:02:05Z'); later.year.name; --> 'year' later.year.range; --> 31556900 later.year.val(d); --> 2013 later.year.isValid(d, 2013); --> true later.year.extent(); --> [1970, 2099] later.year.start(d); --> 'Tue, 01 Jan 2013 00:00:00 GMT' later.year.end(d); --> 'Tue, 31 Dec 2013 23:59:59 GMT' later.year.next(d, 2014); --> 'Wed, 01 Jan 2014 00:00:00 GMT' later.year.prev(d, 2012); --> 'Mon, 31 Dec 2012 23:59:59 GMT'
Later is fully extensible and it is easy to create your own custom time periods that can be used to define new schedules. To keep things simple, we'll walk through creating a new time period for indicating morning, afternoon, and evening. For our purposes, morning will be before noon and have a value of 0, afternoon will be before 6pm and have a value of 1, and evening will be before midnight and have a value of 2.
The first step is to create a name and id for the modifier and add it to the later namespace.
later.partOfDay = later.pd = { // interface implementation goes here };
Next, we need to implement the time period interface. First we will just specify the name of this time period.
name: 'part of day',
The range is approximately 6 hours. Though some of our periods are longer and some shorter, we'll use the shortest range which is afternoon at 6 hours.
range: later.h.range * 6,
We then implement val to return the appropriate value based on the definition described previously.
val: function(d) { return later.h.val(d) < 12 ? 0 : later.h.val(d) < 6 ? 1 : 2; },
Then we can use our new val function to implement isValid.
isValid: function(d, val) { return later.pd.val(d) === val; },
The extent is always going to be the same for every day so we can just return a constant array here.
extent: function(d) { return [0, 2]; },
Next we need to implement start and end based on the current time period. This will be the start and end of each part of the day that we've defined.
start: function(d) { var hour = later.pd.val(d) === 0 ? 0 : later.pd.val(d) === 1 ? 12 : 6; // later.date.next is a helper function for creating the date in UTC or // localTime as appropriate return later.date.next( later.Y.val(d), later.M.val(d), later.D.val(d), hour ); }, end: function(d) { var hour = later.pd.val(d) === 0 ? 11 : later.pd.val(d) === 1 ? 5 : 23; // later.date.prev is a helper function for creating the date in UTC or // localTime as appropriate, and automatically adjusts the date to be at // the last second of the specified time return later.date.prev( later.Y.val(d), later.M.val(d), later.D.val(d), hour ); },
Finally, we need to implement next and prev so that you can move to different parts of the day. We need to make sure to increment and decrement the day appropriately if we've already passed the specified value.
next: function(d, val) { var hour = val === 0 ? 0 : val === 1 ? 12 : 18; return later.date.next( later.Y.val(d), later.M.val(d), // increment the day if we already passed the desired time period later.D.val(d) + (hour < later.h.val(d) ? 1 : 0), hour ); }, prev: function(d, val) { var hour = val === 0 ? 11 : val === 1 ? 5 : 23; return later.date.prev( later.Y.val(d), later.M.val(d), // decrement the day if we already passed the desired time period later.D.val(d) + (hour > later.h.val(d) ? -1 : 0), hour ); }
Here is the code for the completed example. To use the time period, just add this code after including Later into your project and before you use it in any schedules.
later.partOfDay = later.pd = { name: 'part of day', range: later.h.range * 6, val: function(d) { return later.h.val(d) < 12 ? 0 : later.h.val(d) < 18 ? 1 : 2; }, isValid: function(d, val) { return later.pd.val(d) === val; }, extent: function(d) { return [0, 2]; }, start: function(d) { var hour = later.pd.val(d) === 0 ? 0 : later.pd.val(d) === 1 ? 12 : 18; return later.date.next( later.Y.val(d), later.M.val(d), later.D.val(d), hour ); }, end: function(d) { var hour = later.pd.val(d) === 0 ? 11 : later.pd.val(d) === 1 ? 5 : 23; return later.date.prev( later.Y.val(d), later.M.val(d), later.D.val(d), hour ); }, next: function(d, val) { var hour = val === 0 ? 0 : val === 1 ? 12 : 18; return later.date.next( later.Y.val(d), later.M.val(d), // increment the day if we already passed the desired time period later.D.val(d) + (hour < later.h.val(d) ? 1 : 0), hour ); }, prev: function(d, val) { var hour = val === 0 ? 11 : val === 1 ? 5 : 23; return later.date.prev( later.Y.val(d), later.M.val(d), // decrement the day if we already passed the desired time period later.D.val(d) + (hour > later.h.val(d) ? -1 : 0), hour ); } };
Using the custom time period is exactly the same as using a built-in time period.
// use our new time period to specify every 15 mins at night var sched = later.parse.recur().every(15).minute().on(2).customPeriod('pd'), next = later.schedule(sched).next(1, new Date(2013, 3, 21)); console.log(next.toUTCString()); --> Sun, 21 Apr 2013 18:00:00 GMT