A powerful time query library for timeboxing your features using a simple interface resembling a natural time capsule. Working with time and time zones has never been easier.
npm install -s @gopuff/timecapsulejs
// Current day is December 26, 2020.
// You're preparing for your New Year day promotion feature.
const timeCapsule = TimeCapsule.create({
// January 1, 2021 at 12:00 am
open: { year: 2021, month: 1, day: 1 },
// January 2, 2021 at 5:30 am
close: { year: 2021, month: 1, day: 2, hour: 5, minute: 30 },
zone: 'America/New_York',
value: '20% Off'
})
if (timeCapsule.canOpen) {
// The current time is after the open date
// and before the close date of the time capsule.
// Do whatever you need to do.
console.log(`π Happy New Year. Take ${timeCapsule.getValue()} Today Only! π`)
} else if (timeCapsule.isTooEarly) {
console.log(`You can't redeem that New Year promotion, yet β³`)
} else if (timeCapsule.isTooLate) {
console.log(`That New Year promo has expired π₯`)
}
Easily work with timetables:
// Current time is Monday 12:30pm
const isLunchTime = TimeCapsule.createOpenable().queryAccess({
time: { $thru: ['11:30am', '3:29pm'] },
weekday: { $thru: ['monday', 'fri'] },
})
if (isLunchTime) {
console.log(`Come grab lunch!`)
}
// Current day is Tuesday
const isMeetingLessWorkday = TimeCapsule.createOpenable().queryAccess({
weekday: ['tue', 'thu']
})
if (isMeetingLessWorkday) {
console.log(`No meetings today! Enjoy your heads down time.`)
}
Read on for more complex and convenient usage.
Many features may have to do with adding a feature at a future date and then removing it at a farther date. Your only current option may be to wait until that date comes, stop what you're doing, and get that time-sensitive (and many times temporary) feature out. Then when a farther date comes, you have to stop what we're doing and remove that feature via another deploy. This is especially bad on the weekends or your vacation time.
Time capsules gives you a better option. Build and deploy all those time-sensitive features now and let them turn themselves on and off in the future when their time come and pass.
It works just as you would expect a natural time capsule to: put something in it, set a time it can be opened, and (optionally) provide a time that it should be destroyed (closed), never to be opened again, after it is opened.
The only requirement is an explicit open
date configuration object; at least a year
is required in this configuration. A close
date configuration can also be provided; this must be a date that exclusively follows open
.
Additionally, you can set the time zone for the time capsule so, regardless of where a user is, the time capsule's open and close dates are always in relation to your desired time zone. A good example is if you want a feature to only be enabled during the business hours of your headquarters, say Philadelphia; in such case, you can set the time zone to America/New_York
.
We use Luxon, "A powerful, modern, and friendly wrapper for Javascript dates and times", under the hood for immutable time manipulation, so our configuration objects, open
and close
, require a form that can be converted to a Luxon.DateTime
.
So long as your open
and close
datetime configurations are valid for Luxon.DateTime.fromObject({...})
or new Date(...)
, they can be used for creating a time capsule.
import TimeCapsule from '../lib/timeCapsule'
const TimeZone = {
losAngeles: 'America/Los_Angeles',
newYork: 'America/New_York',
}
// Current time is 6/20/2020 at 12:30pm
const timeCapsule = createTimeCapsule({
// 06/24/2020 at 9:30am
open: {
year: 2020,
month: 6,
day: 24,
hour: 9,
minute: 30,
},
// optional: defaults to client's local time zone
zone: TimeZone.newYork,
// The end of the day: 11:45pm
// "close" is optional. It's set to the end of time if not provided
close: {
year: 2020,
month: 6,
day: 24,
hour: 23,
minute: 45,
},
// "value" is also optional
value: 'Some cool stuff from the past',
})
As a convenience for those times when you just want to quickly create a time capsule that can be opened now so that you can quickly query it with #queryAccess()
(discussed below), you can simply call to #createOpenable()
:
import TimeCapsule from '../lib/timeCapsule'
const timeCapsule = TimeCapsule.createOpenable()
console.log(timeCapsule.canOpen)
// Will always print true
This simply createa s time capsule with the minimal config of open
with the year
field being one year before the current year. If the current day was June 20, 2020, that would look like the following:
const timeCapsule = TimeCapsule.create({ open: { year: 2020 } })
console.log(timeCapsule.canOpen)
// Will always print true
Once you have a time capsule, you can check if you can open it using #canOpen
const myFeatureIsEnabled = timeCapsule.canOpen
For more complex time needs, You can check if you can open a time capsule based on a timetable query using #queryAccess()
.
The idea here is that a capsule can become open at one point in time, but only accessible at certain times.
Think of this in the context of a business. A company becomes registered and open for business on a single, specific day in time, but patrons can only access it on certain days and at certain times based on its timetable (schedule).
timeCapsule.queryAccess({...})
returns true
iff the capsule is open (timeCapsule.canOpen === true
) and the client's current time meets the provided timetable (query).
If the time capsule has a specified timezone, the client's current time will be converted to that timezone before the query is executed against it.
import TimeCapsule from '../lib/timeCapsule'
// Current time is Monday 12:30pm
const timeCapsule = TimeCapsule.createOpenable()
// returns FALSE for Breakfast
timeCapsule.queryAccess({
time: { $thru: ['7am', '11:29am'] },
weekday: { $thru: ['mon', 'friday'] },
})
// returns FALSE for Brunch
timeCapsule.queryAccess({
time: { $thru: ['10am', '3:29pm'] },
weekday: ['saturday', 'sun'],
})
// returns TRUE for Lunch
timeCapsule.queryAccess({
time: { $thru: ['11:30am', '3:29pm'] },
weekday: { $thru: ['monday', 'fri'] },
})
import TimeCapsule from '../lib/timeCapsule'
const createTimeCapsule = TimeCapsule.create
const TimeZone = {
losAngeles: 'America/Los_Angeles',
newYork: 'America/New_York',
}
const capsule = createTimeCapsule({
// 06/24/2020 at 9:30am
open: {
year: 2020,
month: 6,
day: 24,
hour: 9,
minute: 30,
},
zone: TimeZone.newYork, // EDT (optional: defaults to client's local time zone)
// The end of the day: 11:45pm
// "close" is optional. It's set to the end of time if not provided
close: {
year: 2020,
month: 6,
day: 24,
hour: 23,
minute: 45,
},
// "value" is also optional
value: 'Some cool stuff from the past',
})
if (capsule.canOpen) {
// The current time is after the open date of the capsule and before the close date
// and before the close date of the time capsule.
// Do whatever you need to do.
console.log(capsule.getValue(), 'π π')
} else {
// The time capsule isn't ready to be opened yet
// or the open period has passed, and it closed forever.
console.log(`The stars are not in alignment π`)
}
if (capsule.canOpen) {
// The current time is after the open date of the capsule.
// Do whatever you need to do.
console.log(capsule.getValue(), 'π π')
} else if (capsule.isTooEarly) {
// The current time is before the open date of the capsule.
console.log(`You can't redeem that promotion, yet β³`)
} else if (capsule.isTooLate) {
// The current time is after the close date of the capsule.
console.log(`That promo has expired π₯`)
}
See the tests for the full range of capabilities.