Fun with Dates

TK
Level Up Coding
Published in
4 min readApr 14, 2020

--

Photo by Mockaroon on Unsplash

This post was first published at TK's blog.

As an ex-Rubyist, I always liked to work with Ruby dates (mental note: not the timezone part). I liked the human way on how Ruby and Rails provide methods to handle the Date object.

In Ruby, we can get the current date by doing:

This is pretty cool! I can send a simple message to the Date object “hey, provide me the today date" by calling the today method.

Or simply get the year, month, day.

Using Rails, it is also possible to call the yesterday method.

Rails also provide other interesting APIs: beginning_of_month, minutes.ago, days.ago.

So after a long time with Ruby and Rails, I started using JavaScript more and more. But the JavaScript Date object was really strange for me. I wanted to use all the Ruby/Rails date APIs but in JavaScript and Typescript.

I didn’t want to monkey patch or build new methods in the JavaScript Date object. I could just provide some simple functions and handle the Date internally.

Dating dates

First things first: I wanted to better understand the Date object. How do we create it?

By simply instantiate the Date object. We get the representation of now (the current date).

The other APIs I need to try was: getDate, getMonth, and getFullYear. These are all methods to handle the date.

We could experiment with a whole bunch of other methods here, but I think we are good to move to the next part.

Fun with dates

In this part, we will build functions! I wanted to try creating this API:

  • day
  • month
  • year
  • today
  • yesterday
  • beginningOfDay
  • beginningOfMonth
  • beginningOfYear
  • get(1).dayAgo
  • get(2).daysAgo
  • get(1).monthAgo
  • get(2).monthsAgo
  • get(1).yearAgo
  • get(2).yearsAgo

day, month, and year

In this case, we provide a date and it will return the day of this date we provided.

And we can use it like:

today and yesterday

With today function, we could just return the new Date() and we are good. But this returns the representation of now with "time" included.

But it would be great to return the beginning of the day. We could simply pass the day, month, and year to the Date and it will generate this for us.

Great. The yesterday function would work very similarly. Just subtract the day and we are good to go.

But what happens when we subtract the day if the day is the first day of the month?

And what happens if it is the first day of the year?

Yes, JavaScript can be pretty smart too!

With these two new functions, we can also refactor the logic to get the separated date into a separate function.

Let’s improve this! This returned type could be a Typescript type.

Less verbose now:

In this case, we are always returning the day, month, and year attributes of the current date. But what if we want to pass a different date? A new argument to the rescue:

Now we have a function that can receive a new date, but if it doesn’t, it just use the default value: the representation of now.

How does our functions today and yesterday look like now?

Both functions use the getSeparatedDate function to get the Date attributes and return the appropriate date.

Beginning of everything

To build the beginningOfDay, it would look exactly of the today function, as we want to the current date but at the beginning of the day.

Nothing special here.

But just minor comment if you didn’t notice: At first, I’m built this function to get the beginning of the day of the current day. But I wanted to make it flexible enough to get the beginning of the day of other days too.

So “argument”, right? Now the function receives a date, but it is flexible to not receive it too. I just handle it with a default value of the current date.

For the beginningOfMonth, it will look like pretty much the same, but instead of using the day, we just set it to 1.

You got it, the beginningOfYear is similar. But also changing the month attribute.

Traveling back in time

Now the get(1).dayAgo API. We could build a get function that receives a number and return an object like:

For each attribute of this object, it would be the returned value we expect.

What about a DateAgo type?

And now using the new type:

We build each attribute: dayAgo, monthAgo, and yearAgo by basically handling the Date object as we know.

But now we also need to implement the object in the plural: daysAgo, monthsAgo, and yearsAgo. But only for a number greater than 1.

For these new attributes, we don’t need to create a whole new date again. We can use the same value from the singular attributes.

We also need to handle the number received.

  • if it is greater than 1: return the object with plural attributes
  • otherwise: return the object with singular attributes
  • In this case, I also created the DatesAgo type and used the Typescript Union Type feature.
  • We reuse the singular values.
  • And do a simple ternary to handle the number received.

But what if we pass a 0 or negative value? We can throw an error:

The Date can be fun too. Learn the basic concepts and just play around with it, you’ll like! I hope this post was valuable to you!

Resources

--

--