npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@gopuff/timecapsulejs

v1.2.0

Published

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.

Downloads

402

Readme

TimeCapsule.js

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

Simple Interface:

// 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.

Motivations

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.

Interface

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.

Date configuration expectations

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.

How to Use

Create 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',
})

Create an openable time capsule (convenience)

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

.canOpen

Once you have a time capsule, you can check if you can open it using #canOpen

const myFeatureIsEnabled = timeCapsule.canOpen

.queryAccess(query)

For more complex time needs, You can check if you can open a time capsule based on a timetable query using #queryAccess().

The idea behind the name of #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).

How #queryAccess() works

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.

Example usages

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'] },
})

Example usage

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 🌑`)
}

Additional example:

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.