Java Lesson 19: Fun with Dates and Times (in Java)

Advertisements

Hello everybody,

Michael here, and today I’ll be sharing a fun Java lesson on the use of dates and times in Java. I already covered date and time manipulation for both Python and R, but here’s the Java version of this concept.

Now, since the last time I posted a Java lesson, I got a new laptop, but I still plan to use NetBeans as my main IDE for these posts.

When working with dates and times in Java, keep in mind that unlike in Python, Java doesn’t have a single Date class/module that you can easily import or pip install. Java does have a java.time package which allows you to work with date/time manipulation. However, unlike with Python, you can’t import the whole package at once and expect to be able to use all of the package’s classes just like that. Rather, you’ll need to import all the package’s classes (the classes that you want to use) one by one-this is one of the major disadvantages of Java.

To start off our exploration of Java date-time manipulation, let’s first explore the Clock class of the java.time package. Some of the things that the Clock class can do is print out the current time (in both UTC and other time zones) and retrieve your current time zone-both of which would be useful when developing applications that deal with time zones. Execute this code and see what happens:

import java.time.Clock;
public class DateTime {

    public static void main(String[] args) 
    {
        Clock c = Clock.systemDefaultZone();
        System.out.println(c);
    }
    
}

SystemClock[America/Chicago]

Now, what exactly does this code do? Well, it creates an object of the Clock class and prints out the value of the object.

You’re likely wondering what systemDefaultZone is. It’s one of several methods in the Clock class. You can’t create an object of the Clock class on it’s own-by that I mean you can’t create a Clock object that looks like this: Clock c = Clock(). You’ll need to use of the class’s methods-in this case, I used the systemDefaultZone method. All this method does is print out the time zone your computer uses. Since I am in Nashville, TN right now, my system default [time] zone is [America/Chicago], as Chicago also uses Central Standard Time.

The Clock class has other methods, which you can find on this documentation from Oracle-https://docs.oracle.com/javase/8/docs/api/java/time/Clock.html. Explore this website for links related to some of the other classes that I will be discussing in this post.

Next up, let’s discuss the LocalDate class. This class allows you to display dates, but not datetimes or time zones. To start exploring the LocalDate class, let’s first create a simple LocalDate object:

import java.time.LocalDate;
public class DateTime {

    public static void main(String[] args) 
    {
        LocalDate ld = LocalDate.now();
        System.out.println(ld);
    }
    
}

2021-11-15

In this example, I created a simple LocalDate object that prints out today’s date using the .now() method (I ran this code on November 15, 2021). Just as with the Clock class, whenever you create a new object of the LocalDate class, you’ll need to include a class method with your object creation; in this case, I used the now() method of the LocalDate class.

Now, let’s explore some more methods of the LocalDate class by executing this code:

import java.time.LocalDate;
public class DateTime {

    public static void main(String[] args) 
    {
        LocalDate ld = LocalDate.now();
        System.out.println(ld.plusMonths(3));
        System.out.println(ld.getDayOfWeek());
        System.out.println(ld.isLeapYear());
        System.out.println(ld.toEpochDay());
    }
    
}

2022-02-15
MONDAY
false
18946

In this example, I still created a LocalDate object called ld that uses the LocalDate class’s .now() method. However, I added four output lines (referenced with System.out.println()) which generate four different outputs based on four different methods. Here’s an explanation of each output:

  • The first output-2022-02-15-was generated through the LocalDate class’s .plusMonths() method. The .plusMonths() method takes in one parameter-an integer that tells Java how many months to add to the date in the LocalDate object. In this case, I passed in 3 as the parameter of the .plusMonths() method, which tells Java to add 3 months to today’s date-the output is February 15, 2022.
  • The second output-MONDAY-was generated through the .getDayOfWeek() method, which in this case retrieves the current date’s day of the week. November 15, 2021 is a Monday, therefore this method will return MONDAY.
    • Recall that the current date in this example is November 15, 2021.
  • The third output-false-was generated through the .isLeapYear() method, which in this case returns either true or false depending on whether the current year is a leap year. Since 2021 isn’t a leap year, this method returned false.
  • The fourth output-18946-was generated through the interesting .toEpochDay() method. You wouldn’t need to use the .toEpochDay() method much, but I’ll discuss it here anyway. This method simply returns the number of days its been since January 1, 1970-the “epoch time” for computers. Why January 1, 1970? It’s basically an arbitrary date that serves as the “zero point” (or default time) for most operating systems.
    • On my old laptops, when the operating system was having issues, the system date would always be set to January 1, 1970.

Now that we’ve explored the LocalDate class a bit, let’s move on to the LocalTime class. LocalTime is basically the opposite of LocalDate since LocalTime only displays times and timestamps but no dates.

Let’s create a simple LocalTime object using the code below:

import java.time.LocalTime;
public class DateTime {

    public static void main(String[] args) 
    {
        LocalTime lt = LocalTime.now();
        System.out.println(lt);
    }
    
}

21:13:50.623089

Similar to the LocalDate example, I created a LocalTime object using the .now() method. And in case you hadn’t figured it out by now, you can’t create a LocalTime object without including a class method (just as you needed a class method for the Clock and LocalDate objects)

In this case, the LocalTime object I created printed out the current (at runtime) time as set on my laptop-21:13:50.623089. I ran the code at 9:13PM Central Standard Time, but Java will print out the time in 24-hour format (and 21 represents the 9PM hour).

Now, let’s explore four other methods of the LocalTime class (you’ll notice that this code looks syntactically similar to the code in the previous example):

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneOffset;
public class DateTime {

    public static void main(String[] args) 
    {
        LocalTime lt = LocalTime.now();
        System.out.println(lt);
        System.out.println(lt.plusHours(6));
        System.out.println(lt.minusMinutes(45));
        System.out.println(lt.toNanoOfDay());
        System.out.println(lt.toEpochSecond(LocalDate.MAX, ZoneOffset.UTC));
    }
    
}

21:35:06.320094400
03:35:06.320094400
20:50:06.320094400
77706320094400
31556889832772106

Now, just as I did with the four methods in the LocalDate example, let’s explore the four methods I used here:

  • Below the lt output, you’ll see the output 03:35:06.320094400, which was generated from the .plusHours() method. This method takes in an integer parameter (6 in this case) and add that many hours to the current time-in this case, 6 hours from the current [run]time is 3:35AM.
  • The next output is 20:50:06.320094400, which was generated from the .minusMinutes() method. Like the .plusHours() method, the .minusMinutes() method takes in an integer (45 in this case) as the parameter. However, the .minusMinutes() method subtracts a certain amount of minutes from the LocalTime object-in this case, 45 minutes before the current [run]time is 10:50PM.
  • The next output is 77706320094400, which was generated from the .toNanoOfDay() method. This method returns the nanosecond of the current time. In this case, 9:35:06PM is roughly the 77.7 trillionth nanosecond of the day. If the current time was 12:00:00AM, the .toNanoOfDay() method would return 1, as this time would be the first nanosecond of the day.
    • Just so you know, 1 second is equal to a billion nanoseconds.
  • The last output is 31556889832772106, which was generated from the .toEpochSecond() method. This method is conceptually similar to the .toEpochDay() method, since both methods return the amount of time in a certain unit (days or second) since January 1, 1970. However, .toEpochSecond() returns the amount of seconds that have passed since January 1, 1970 at 12:00:00AM, which in this case is roughly 31.6 quadrillion seconds.
    • The ZoneOffset class was needed for the .toEpochDay() method, but don’t worry about it otherwise.

Next up, let’s explore the LocalDateTime class. You might be able to figure out what this class does based off the class name alone, but in case you didn’t, this class displays date-time objects-which are objects that display dates and times (in the same string).

As I did for both LocalDate and LocalTime, I will create a simple object of the LocalDateTime class using the .now() method:

import java.time.LocalDateTime;
public class DateTime {

    public static void main(String[] args) 
    {
        LocalDateTime ldt = LocalDateTime.now();
        System.out.println(ldt);
    }
    
}

2021-11-20T07:22:10.017889200

This example prints out the current date-time (at runtime)-November 20, 2021 at 7:22AM.

Now, let’s explore four different methods of the LocalDateTime class:

import java.time.LocalDateTime;
public class DateTime {

    public static void main(String[] args) 
    {
        LocalDateTime ldt = LocalDateTime.now();

        System.out.println(ldt.minusDays(60));
        System.out.println(ldt.plusMonths(4));
        System.out.println(ldt.withDayOfYear(60));
        System.out.println(ldt.getDayOfMonth());
    }
    
}

2021-09-21T07:29:56.515749900
2022-03-20T07:29:56.515749900
2021-03-01T07:29:56.515749900
20

Let’s explore each of the methods and their corresponding outputs:

  • The first output-2021-09-21T07:29:56.515749900-was generated through the LocalDateTime class’s .minusDays() method, which in this example takes in an integer as a parameter and subtracts that amount of days from the current date-time. In this case, 60 days subtracted from the current date-time equals September 21, 2021 at 7:29AM.
  • The second output-2022-03-20T07:29:56.515749900-was generated through the LocalDateTime class’s .plusMonths() method. Like the .minusDays() method, this method takes in an integer parameter; however, this method will add a certain number of months to the current date-time. In this case, 4 months added to the current date-time equals March 20, 2022 at 7:29AM.
  • The third output-2021-03-01T07:29:56.515749900-was generated through the .withDayOfYear() method. This is one of the LocalDateTime class’s more interesting methods since it oftentimes returns a different date from the date in the date-time object. This method, like the previous two I discussed, takes in an integer as a parameter; in this case, the method will return the date corresponding to the Xth day of the year. Since I passed 60 as the integer parameter, this method will return the date March 1, 2021 (the time part of the date-time object remains unchanged). Had I wrote and ran this code last year, this method would’ve returned February 29, 2020, as February 29 is the 60th day of the year in leap years.
  • The last output-20-was generated through the .getDayOfMonth() method. In this case, the method simply retrieves the day of the month of the current datetime; since the current date [as of runtime] is November 20, 2021, this method will return 20 since it’s currently the 20th day of the month.

Last but not least, let’s explore the DateTimeFormatter class. This class is different from the previous three classes we discussed because unlike those three classes, this class doesn’t return a datetime object. Rather, this class generates a formatted datetime object from an exisiting datetime object. Let me demonstrate this concept with the code below:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class DateTime {

    public static void main(String[] args) 
    {
        LocalDateTime ldt = LocalDateTime.now();
        System.out.println("DateTime before formatting: " + ldt);
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MM-dd-yy HH:mm");
        String formattedDateTime = ldt.format(dtf);
        System.out.println("DateTime after formatting: " + formattedDateTime);
    }
    
}

DateTime before formatting: 2021-11-28T09:01:48.974227300
DateTime after formatting: 11-28-21 09:01

Ok, so this example looks more complicated than our previous examples. As you can see from the code above, to be able to format a datetime object, we first need to create a datetime object of the LocalDateTime class.

Next, we’d need to create a datetime formatter object using the DateTimeFormatter class. We’d use this class’s .ofPattern() method and pass in a String pattern as the method’s parameter. In this example, I passed the pattern MM-dd-yy HH:mm into the .ofPattern() method; this pattern will display the datetime object with the date portion being displayed month first (followed by the day and year) and the time portion being displayed with just the hour and minute.

  • When specifying a datetime pattern to use for the .ofPattern() method, the month (MM) and hour (HH) will always be written with capital letters.
  • If you wanted to incorporate the full year into the output (2021 as opposed to just 21), you’ll need to write yyyy in place of yy.

Now, as you may have figured out from the code, the datetime formatter will only specify the pattern to use for the datetime object-the formatter (dtf) won’t actually format the DateTime object. Take a look at the line of code with the formattedDateTime object. In order to actually format the LocalDateTime object (ldt), you’ll need to use that object’s .format() method and pass in the object containing the pattern you want to use (dft in this case) as the .format() method’s parameter.

I also included two output lines-one that shows the current datetime before formatting and another one that shows the current datetime after formatting. Since I ran this code at 9:01AM Eastern Standard Time on November 28, 2021, the datetime object after formatting is 11-28-21 09:01.

Thanks for reading,

Michael

Python Lesson 17: Date & Time Manipulation in Python

Advertisements

Hello everybody,

Michael here, and today’s lesson will be on performing date & time manipulation in Python. Now I know I did a date & time manipulation lesson in R (check out R Lesson 19: Fun With Dates & Times), but I want to show you how it’s done in Python.

Before I get started with any coding examples, I think it will be important to mention that dates aren’t data types. However, we can import a datetime module to create date & time objects; to import the datetime module, use the line import datetime.

Now, here’s how to use the datetime module to display the current date and time:


now = datetime.datetime.now()

print(now)

2021-04-15 22:16:45.356841

In this example, I created a datetime object-now-that displays the current date and time (using the 24-hour format for time) using the datetime.now() method of the datetime module. Simple enough, right?

Well, along with displaying the current date & time, the datetime module also has several format codes to retrieve information about a datetime object. Let’s say we wanted to retrieve the current month (fully spelled out) and the current day of the week (in shorthand). Here’s how to do so:

now = datetime.datetime.now()

print(now.strftime("%a"))
print(now.strftime("%B"))

Thu
April

In this example, I am retrieving the current day of the week (in shorthand) and the current month (fully spelled out) from the current datetime-April 15, 2021 10:16:45PM. To retrieve the shorthand day of the week, I used the format code %a and to retrieve the fully spelled out month, I used the format code %B. Also, in order to use these format codes, I need to use them as parameters in the function strftime.

Here’s a list of all the format codes you can use with the strftime function (all examples refer to the now object):

  • %a-returns the shorthand version of the weekday.
    • example: %a would return Thu (which is shorthand for Thursday)
  • %A-returns the fully spelled out version of the weekday
    • example: %A would return Thursday (the name of the weekday spelled out)
  • %w-returns the corresponding number of the weekday; the weekdays are numbered from 0-6, with 0 being Sunday and 6 being Saturday
    • example: %w would return 4 (Thursday corresponds to 4)
  • %d-returns the day of the month (which can range from 01-31)
    • example: %d would return 15 (the day of the month in the now object is 15)
  • %b-returns the shorthand version of the month
    • example: %b would return Apr since the month for the now object is April.
  • %B-returns the fully spelled out version of the month
    • example: %B would return April (which is the month for the now object)
  • %m-returns the number of the month (which can range from 01 to 12):
    • example: %m would return 04 since April is the 4th month of the year
  • %y-returns the last two digits of the year:
    • example: %y would return 21 since the year is 2021
  • %Y-returns the full version of the year:
    • example: %Y would return 2021 since the year is 2021
  • %H-returns the hour according to a 24-hour clock:
    • example: %H would return 22 since the time is 10:16 PM.
  • %I-returns the hour according to a 12-hour clock:
    • example: %I would return 10 since the time is 10:16 PM.
  • %p-returns AM or PM depending on whether the time is before or after 12 noon.
    • example: %p would return PM since the time is 10:16 PM.
  • %M-returns the minute of the time part of the datetime object (ranging from 00-59)
    • example: %M would return 16 since the minute of the time part of now is 16.
  • %S-returns the second of the time part of the datetime object (ranging from 00-59)
    • example: %S would return 45 since the second of the time part of now is 45 (the full time is 10:16:45 PM)
  • %f-returns the millisecond part of the datetime object (ranging from 000000-999999)
    • example: %f would return 356841 since the millisecond part of now is 356841 (the full time with milliseconds is 10:16:45.356841 PM)
  • %z-returns the difference between the current time and UTC time (in hours)
    • example: I know I didn’t set a time-zone for now, but if I did, %z would return -0600 since I’m writing this post from the US Central Time Zone and US CST is 6 hours behind UTC.
  • %Z-returns the time-zone
    • example: %Z would return CST as I’m currently in the US Central Time Zone (this would work if I had set a time zone)
  • %j-returns the day number of the year (ranging from 001-366)
    • example: %j would return 105 as April 15 is the 105th day of the year.
    • An important thing to note here is that if the date for now was set to April 15, 2020, %j would return 106 since April 15 is the 106th day of the year in leap years.
  • %U-returns the week number of the year (ranging from 00-53); this format code assumes weeks start on Sunday
    • example: %U would return 20 as April 15, 2021 falls on the 20th week of the year 2021.
    • The %U format code would return 01 for January 3-9, 2021, as this is the first full week of the year. However, for January 1-2, 2021, %U returns 00. Interestingly, for December 27-31, 2020 (which falls on the same week as January 1-2, 2021), %U would return 52.
  • %W-returns the week number of the year (ranging from 00-53); unlike the format code %U, this format code assumes weeks start on Monday
    • example: %W would also return 20 since it is still the 20th week of the year 2021 (even though %W uses the weeks-starting-on-Monday system)
  • %c-returns the local date and time; the local date and time is displayed using this format-(day of week) (month & day) (local time in 24-hour format) (year)
    • example: %c would return Thu Apr 15 22:16:45 2021 as that is the local time stored in the now object.
    • Only the hours, minutes, and seconds are returned from the local time.
  • %x-returns the date in mm/dd/yy format
    • example: %x would return 04/15/21
  • %X-returns the local time in 24-hour format
    • example: %X would return 22:16:45
  • Just as with regex special sequences, the letter casing can be very easy to mix up between format codes, so keep that in mind.
  • Date format codes start with percent signs while regex special sequences start with backslashes (it can be very easy to confuse date format codes with regex special sequences).

Now, what if I wanted to create my own datetime object? Here’s how to do so:

date1 = datetime.datetime(2021, 4, 18)

print(date1)

2021-04-18 00:00:00

In this example, I created my datetime object date1 and set the parameters equal to 2021, 4, and 18, respectively. When I printed the date1 object, I got the output 2021-04-18 00:00:00.

How did I get this output? Well, since I used 2021, 4, and 18 as parameters, I got the date 2021-04-18 since the year is the first parameter to set when creating a datetime object followed by the month and day.

However, you’re probably wondering how I got the time 00:00:00. See, when I create a datetime object, I can not only set a date but I can also set a time. Aside from the year, month, and day, I can also set an hour, minute, second, millisecond, and time zone parameter. All of these parameters are optional when creating a datetime object, and if no value is specified for each of these parameters, 00 is the default value-hence why the outputted time was 00:00:00.

Now that I’ve shown you the basic things you can do with the datetime package, let’s discuss how to perform date manipulation.

First of all, what if we wanted to calculate the difference between two dates? Here’s how we would do so:

date2 = datetime.datetime(2021, 9, 9)
date3 = datetime.datetime.now()
delta = date2 - date3

print("There are" ,delta.days, "more days until the 2021 NFL season.")
There are 143 more days until the 2021 NFL season.

In this example, I created two datetime objects-date2 and date3-and created a variable delta to determine the difference between the two dates.

  • Just so you know, the date being referenced in now is April 18, 2021. Also, the 2021 NFL season starts on September 9, 2021, hence why the date2 parameters are (2021, 9, 9).

After subtracting the two datetime objects, I then get the message There are 143 more days until the 2021 NFL season. Just for reference, here is the print statement I used: print("There are" ,delta.days, "more days until the 2021 NFL season."). The delta.days statement returns the number of days between the two datetime objects.

Now, what if you wanted to find the amount of weeks between two dates? Here’s how to do so:

date2 = datetime.datetime(2021, 9, 9)
date3 = datetime.datetime(2021, 4, 18)
delta = date2 - date3

print("There are" ,round(delta.days/7, 1), "more weeks until the 2021 NFL season.")

There are 20.6 more weeks until the 2021 NFL season.

Unfortunately, finding the number of weeks between two dates isn’t as simple as using delta.weeks (I know because I tried this). If you want to find the amount of weeks between two dates, simply divide the result of delta.days by 7. The decimal generated by delta.days/7 is quite long, so it’s often useful to round the decimal (using the round function) to either 1 or 2 decimal places as I did above.

Now let’s see how we can get the amount of months between two dates:

date2 = datetime.datetime(2021, 9, 9)
date3 = datetime.datetime(2021, 4, 18)
delta = date2 - date3

print("There are" ,round(delta.days/30, 1), "more months until the 2021 NFL season.")

There are 4.8 more months until the 2021 NFL season.

In this example, I used the same approach to finding the amount of months between two dates as I did when I was trying to find the amount of weeks between two dates (even rounding the quotient to one decimal place). The only difference between this example and the previous example is that I divided delta.days by 30 to find the amount of months between the two dates.

  • You probably guessed this, but there is no delta.months function. Hence why we need to divide the result of delta.days by 30.
  • In order to get the amount of months between two dates, you don’t have to divide delta.days by 30. 28 might work, but when I tried dividing delta.days by 28 in the above example, I got 5.1 (I felt that 4.8 was more accurate).

Now I’ve shown you how to create datetime objects as well as calculate the difference (in days, weeks, and months) between two datetime objects. What if we wanted to find out the date that would be X days before or after a certain date? Here’s how to do so:

from datetime import timedelta

date4 = datetime.datetime.now()

newdate = date4 + timedelta(days=20)

print(newdate)

2021-05-09 22:10:53.372408

In order to add or subtract days from a certain date, I would first need to import the timedelta module from the datetime package (use the line from datetime import timedelta). In this example, I created a datetime object date4 and set it to the current date & time (April 19, 2021 at 10:10 PM). I then created a newdate object and set it equal to the value of date4 plus 20 days from date4 using the timedelta(days=20) function-I then got the result of 2021-05-09 22:10:53.372408.

Now, what if you wanted to subtract 20 days from date4? Here’s how you would do so using the timedelta function:

date4 = datetime.datetime.now()

newdate = date4 - timedelta(days=20)

print(newdate)

2021-03-30 22:20:01.464021

In order to find out the datetime that falls 20 days before date4, all I needed to do was replace the plus sign with a minus sign and VOILA!-I get the new datetime (March 30, 2021 at 10:20 PM).

  • Using this line of code for newdatenewdate = date4 + timedelta(days=-20)-would’ve worked as well.
  • Unfortunately, you can only add or subtract dates with timedelta-multiplying, dividing, or raising dates to a certain power won’t work with timedelta (I know because I tried this and kept getting TypeErrors).

The timedelta function not only calculates days before or after a certain date. You can also calculate weeks, hours, minutes, seconds, milliseconds, and nanoseconds (yes, timedelta is that precise) before or after a certain datetime.

  • There are 1 million nanoseconds in a millisecond, in case you’re wondering.

Thanks for reading,

Michael

R Lesson 21: Calendar Plots

Advertisements

Hello everybody,

Michael here, and today’s post will be an R lesson on calendar plots in R. Now I know I already did a lesson on dates and times in R, but this lesson will focus on creating cool calendar plots in R with the calendR package.

Before we start making calendar plots, let’s install the calendR package.

Once we install these packages, let’s start by building a simple calendar plot with this line of code-calendR(). Here’s the output we get:

As you can see, the calendR() prints out a calendar for the current year (2020). If no parameter is specified, calendR() print the current year’s calendar by default.

If you want to print the calendar for a different year, specify the year in the parameter. Let’s say you wanted to print last year’s calendar (2019). To print last year’s calendar, use this line of code-calendR (year=2019). Here’s the output from that line of code:

OK, now let’s try some other neat calendar tricks. First, let’s set up our calendar plot to have weeks start on Monday (weeks start on Sunday by default). Here’s the code to do so:

calendR(start="M")

Since I didn’t specify a year in the parameter, calendR will print out a calendar of the current year by default.

Awesome! Now let’s add some color to certain special days. Here’s the code to do so:

calendR(special.days = c(61,91,121,331,360,366), special.col="lightgreen", low.col="white")

When adding color to certain special days, here are some things to keep in mind:

  • The calendR function has its own parameter to denote special days-aptly named special.days. Special.col specifies a color for the special days while low.col specifies a color for all other days.
  • To choose which days to highlight, specify the corresponding number for the day you want to highlight (e.g. 1 corresponds to January 1, 2 to January 2, and so on). Remember that if the calendar plot is for a leap year (like the plot above), day numbers from March 1 onward will be different than they would be in a non-leap year (e.g. the day number for March 2 in a non-leap year would be 61, while in a leap year it would be 62).

Now what if we wanted to highlight all of the weekends? Let’s see how we can do that. Use this line of code to highlight the weekends in 2020:

calendR(special.days="weekend")

Now what if we wanted to add several color-coded events to the calendar? Here’s the code to do that:

events <- rep(NA, 366) 
events[1] <- "Holidays"
events[45] <- "Holidays"
events[146] <- "Holidays"
events[186] <- "Holidays"
events[251] <- "Holidays"
events[305] <- "Holidays"
events[331] <- "Holidays"
events[360] <- "Holidays"
events[366] <- "Holidays"
events[61] <- "My Birthday"
calendR(special.days=events, special.col=c("green", "orange"), legend.pos="right") 

How did I create this calendar plot? Let me give you a step-by-step breakdown:

  • In order to add events to the calendar plot, you would first need to create a vector of NA values. My vector is called events, but the name of the vector doesn’t matter. Just remember to make the vector the same length of the number of days of days as the corresponding year.
    • Hint-the vector will have a length of 366 for leap years (such as 2020) and 365 for non-leap years (such as 2021)
  • Next, add all of the events you want on the calendar to the corresponding day of the year on the vector. For example, two days I wanted to highlight were January 1 and May 25 (New Year’s Day and Memorial Day 2020, respectively), so I added these two days to positions 1 and 146 of the events vector, as January 1 and May 25 were the 1st and 146th days of 2020, respectively.
    • If you want multiple dates under the same event category (e.g. “Holidays” in this example) , you’ll have to list all of the corresponding days of the year in the vector 1-by-1, unless the dates are consecutive (e.g. an event that goes on for 7 consecutive days). You can’t list all of the corresponding days of the year in a comma-separated array like you can in Java or Python (I know because I tried to do this and it didn’t work).
  • Once you added all of the events to the calendar, use the calendR function to create the color-coded calendar plot with events. The function takes four parameters, which include:
    • year-the year for the calendar plot; if a year isn’t specified, calendR will create a plot of the current year by default (as it does in this example)
    • special.days-the vector of events you created (events in this example)
    • special.col-the colors to represent each of the events
      • Only use as many colors as you have event categories. In this example, I only have two event categories-“My Birthday” and “Holidays”-and thus only use two colors for this function. Also keep in mind that the first color listed will be used for the first event category, the second color for the second event category, and so on.
    • legend.pos-the positioning of the legend on the plot; in this example, legend.pos equals right, which means that the legend will be displayed on the right of the graph

Now, what if you wanted to make a calendar plot for just a single month? Using the current month as an example, here’s how to do so:

calendR(month = 12)

By simply using the code calendR(year = X, month = 1-12) you can create a calendar plot for any month of any year. Remember that if you don’t specify the year, calendR will create a plot for chosen month of the current year (2020) by default.

Great, now let’s add some color to certain days! Here’s the code to do that (along with the corresponding output):

calendR(month = 12, special.days=c(9, 16, 25, 27, 31), special.col="yellow", low.col="white")

OK, what if we wanted to add several color-coded events to the calendar? Let’s see how we can do this:

events2 <- rep(NA, 31)
events2[24:25] <- "Holidays"
events2[31] <- "Holidays"
events2[1:4] <- "Workweek"
events2[16] <- "Birthdays"
events2[27] <- "Birthdays"
calendR(month = 12, special.days=events2, special.col = c("red", "orange", "lightblue"), low.col="white", legend.pos="top") 

The process for adding color-coded events for a month-long calendar plot is the same as it is for a year-long calendar plot, except you would need to make the events vector the length of the days in the month rather than the length of the days in the year. In this case the length of the events vector (called events2 to avoid confusion with the other events vector) would be 31, as there are 31 days in December.

  • Just so you know, low.col in the last two examples refers to the color of the boxes that don’t contain color-coded events.

Great, now let’s say we wanted to add some text to the days. How would we go about this? Here’s how:

calendR(month = 12, text=c("Battlebots", "Birthday", "Christmas", "Birthday", "New Year's Eve"), text.pos=c(3, 16, 25, 27, 31), text.size=4.5, text.col="green4")

Here’s a step-by-step breakdown of how I created this plot:

  • First, I indicated the month I wanted to use for my calendar plot. Since I didn’t specify a year, calendR will automatically plot the chosen month of the current year (December 2020).
  • Next, I created a vector of text I wanted to add to the calendar plot and used text.pos to indicate which days should contain which text (for instance, the first element in the text vector corresponds with the first element of the text.pos vector).
    • Remember to keep the text vector the same size as the text.pos vector.
    • I know this sounds obvious, but know how many days the month on your calendar plot has, or else the calendar plot won’t work. For instance, trying to place text on 32 in this plot won’t work because December doesn’t have a 32nd.
  • Text.size and text.col specify the font size and color of the text, respectively.

Now let’s try something different-creating a lunar calendar, which is a month-long calendar plot that shows the different moon phases on each day of the month. Also, just out of curiosity, let’s create a lunar calendar for next month-here’s the code to do so:

calendR(year = 2021, month = 1, lunar = TRUE, lunar.col="gray60", lunar.size=8)

Here’s a step-by-step breakdown of how I created this lunar calendar:

  • Since I’m creating this lunar calendar for next month, I had to specify both the year (2021) and the month (1), as next month is the January 2021 (crazy, huh).
  • I had to set lunar to TRUE to indicate that this is a lunar calendar
  • Lunar.col signifies the color of the non-visible area of the moons.
  • Lunar.size signifies the size of the moons on the calendar plot.
  • In case you’re wondering what each of the moon phases are, here’s a handy little graphic (feel free to Google this information if you want to learn more about moon phases):

Last but not least, let me show you how we can create a calendar plot with custom start and end dates. A perfect example of this type of calendar plot would be an academic calendar, which I will show you how to create below, using the 2020-21 Metro Nashville Public Schools calendar as an example:

events3 <- rep(NA, 304)
events3[3] <- "Day Off"
events3[6] <- "Day Off"
events3[38] <- "Day Off"
events3[63] <- "Day Off"
events3[66:70] <- "Day Off"
events3[73] <- "Day Off"
events3[84] <- "Day Off"
events3[95] <- "Day Off"
events3[103] <- "Day Off"
events3[117:119] <- "Day Off"
events3[140] <- "Day Off"
events3[143:147] <- "Day Off"
events3[150:154] <- "Day Off"
events3[157:159] <- "Day Off"
events3[171] <- "Day Off"
events3[199] <- "Day Off"
events3[227:231] <- "Day Off"
events3[238] <- "Day Off"
events3[245] <- "Day Off"
events3[299] <- "Day Off"
events3[4] <- "First & Last Days of School"
events3[298] <- "First & Last Days of School"
events3[136:139] <- "Half Days"
events3[293:294] <- "Half Days"
events3[297] <- "Half Days" 

calendR(start_date = "2020-08-01", end_date = "2021-05-31", special.days=events3, special.col=c("salmon", "seagreen1", "gold"), legend.pos="right", title = "Metro Nashville Public Schools 2020-21 Calendar")

So, how did I create this color-coded calendar plot with a custom start and end date? Here’s a step-by-step breakdown of the process:

  • Since I knew the start and end dates I wanted to use for this calendar plot, I created an events vector (named events3 to avoid confusion with the other two events vectors) of length 304. My start and end dates are August 1, 2020 and May 31, 2021, respectively, which cover a 304 day period (including the end date).
  • I then added all of the events to the corresponding days on the vector. Since this isn’t a standard calendar year vector, knowing which element corresponds to which day is trickier. However, I created an excel table with the dates in my date range on one column and the corresponding day in the other column, like this:
  • After inserting all of the events to the corresponding days in the vector, I then used the calendR function to indicate my start_date and end_date.
  • For the special.days argument, I used the events3 vector I created.
  • I then indicated the three colors I wanted to use for the three event categories as the argument for special.col
    • For special.col remember to include the same amount of colors as event categories in this vector. Since I had 3 event categories, I used 3 colors in this vector.
  • I then set legend.pos to right, which tells calendR to place the legend to the right of the calendar plot.
  • Lastly, I set the title of the plot to Metro Nashville Public Schools 2020-21 Calendar.

Thanks for reading,

Michael

R Lesson 19: Fun With Dates & Times

Advertisements

Hello everybody,

It’s Michael, and today I thought I’d do an R lesson (which I haven’t done in almost 9 months). Today’s R lesson will be a little different, as it’s not an analysis. Rather, it’s a demo that shows what R can do beyond performing analyses-in today’s post, I’ll show you how to work with dates and times in R, as well as manipulate them with a handy little package called lubridate.

After installing the lubridate package, let’s start to play around with it. First, let’s create a date in three different formats:

In this example, I displayed a date in three different formats (year-month-day, month-day-year, day-month-year). Notice how the different date formats use different separators. For instance, the year-month-day format doesn’t use separators while the month-day-year format uses dashes and the day-month-year format uses backslashes.

  • Keep in mind these separators aren’t necessary, and if you use other separators for certain formats (or no separators at all), that would be perfectly acceptable. Just don’t incorrectly place certain elements of the date (in other words, don’t place the year first if you’re using month-day-year formatting).

 

Ok, so creating dates is only the basics of what the lubridate package can do-and we haven’t even gotten to the fun parts yet. For instance, did you know you could include a time with your date?:

In this example, I created the variable dateandtime, which contains today’s date (April 26, 2020) along with the time (12:10) using the mdy_hm function, which allows me to include the date (in month-day-year format) along with the time (only the hour and minute though).

  • You can also add an s to the mdy_hm function if you want to include seconds in the date-time object.
  • The time only works with 24-hour notation (more commonly known as “military time”), so trying to write something like “01:15 PM” wouldn’t work-unless you could figure out how to concatenate the “AM” or “PM” onto the end of the date-time object.
  • You could also change the formatting of the date in the date-time object, but remember to write the function according to the formatting you chose. For instance, if you chose to use year-month-day formatting, remember to write the function as ymd_hm (or ymd_hms if you choose to include  the seconds)

 

But wait, there more you can include in a date-time object! Yes, you can also include the time-zone in your date-time object. See, the date-time object defaults to UTC, or Coordinated Universal Time. For those that don’t know what Coordinated Universal Time is, it’s not a time zone, but rather a 24-hour time standard used to synchronize world clocks. In other words, it’s the base point for all other time zones in the world, as they are determined by their distance from the UTC. Also, keep in mind that while the UTC doesn’t adjust to daylight savings time clock changes, the difference between the UTC and the local time does change. For instance, the difference between the UTC and US Central Time Zone is 6 hours when daylight savings time isn’t in place (from the first Sunday in November to the second Sunday in March), but only 5 hours when daylight savings time is in place.

So, let’s see what happens when we add the time-zone to our date-time object:

In this example, I added the US Central Time Zone to the date-time object (I chose Central Time since I am currently in Nashville, TN, which is in the Central Time Zone). The way to add the time-zone to a date-time object is to use the variable tz and set tz to US/(choose time zone). You can’t write the name of a city and expect R to recognize it (I know, since I tried to write US/Nashville and got an error from R).

  • I’m impressed that R knew the US is in Daylight Savings Time since the date-time object did have CDT (Central Daylight Time, as opposed to Central Standard Time) besides it. Then again, R probably looked at the date and time-zone and correctly assumed that the US is in Daylight Savings Time.

The next thing I want to show you is how to extract certain information in a date-time object. Here’s an example of that (using out dateandtime2 object):

All in all, there are 10 functions to extract information from a date-time object. Here’s an explanation of each of them:

  • second-extracts the second from the date-time object. In this example, second is zero since I didn’t include any seconds in this date-time object.
  • minute-extracts the minute from the date-time object. In this example, minute is 5 since the time in dateandtime2 is 13:05
  • hour-extracts the hour from the date-time object. In this example, hour is 13.
  • day-extracts the day from the date-time object. Since the date I used is April 26, 2020, 26 is given as the day
  • wday-extracts the number of the weekday from the date-time object. Since lubridate assumes the week starts on Sunday (some calendars start the week on Monday), Sunday is wday 1, Monday is wday 2, and so on until you get to Saturday (wday 7).
  • yday-extracts what day of the year the date is. In simpler terms, April 26, 2020 is the 117th day of 2020, so 117 is displayed.
  • week-extracts what week of the year the date falls on. Since April 26, 2020 is the 17th week of 2020, 17 is be displayed.
  • month-extracts the numerical value of the month, which can range from 1 (January) to 12 (December). Since April is the 4th month of the year, 4 is displayed
  • year-extracts the year from the date, which is 2020 in this case
  • tz-extracts the timezone from the date-time object (provided you set a timezone). In this case, the tz is US/Central, which is the US’s Central Time Zone.

Next, Iet’s demonstrate how to convert a date-time object into a different time zone:

This date-time object contains the date 05-02-2020 and the time 15:50 (which means 3:50PM). The tz is set to US/Central, which represents the US’s Central Time Zone (and my current city of Nashville, TN is in the Central Time Zone).

But what if I wanted to call some relatives in Bogota, Colombia?  What time would it be there? Well, the with_tz function can help with figuring out this question. Simply use you date-time object and the timezone you wish to convert to as the parameters for this function. When I tried to find out the time in Bogota, Colombia, it turns out that when it’s 3:50PM in Nashville, TN, it’s also 3:50PM in Bogota, Colombia. The -05 means it’s five hours behind UTC (likewise, a +05 would mean that it’s five hours ahead of UTC).

Now, if it’s 3:50PM in Nashville, TN, what time would it be in Paris, France? Using the with_tz function, we can see that it’s 10:50PM in Paris, France, meaning that Paris is 7 hours ahead of Nashville. The CEST stands for Central European Summer Time.

But how would you know which timezone to use? Here’s a nice little hack-type in OlsonNames() into the compiler and you will see the list of all possible time-zones that lubridate will accept:

[1] “Africa/Abidjan” “Africa/Accra” “Africa/Addis_Ababa” “Africa/Algiers”
[5] “Africa/Asmara” “Africa/Asmera” “Africa/Bamako” “Africa/Bangui”
[9] “Africa/Banjul” “Africa/Bissau” “Africa/Blantyre” “Africa/Brazzaville”
[13] “Africa/Bujumbura” “Africa/Cairo” “Africa/Casablanca” “Africa/Ceuta”
[17] “Africa/Conakry” “Africa/Dakar” “Africa/Dar_es_Salaam” “Africa/Djibouti”
[21] “Africa/Douala” “Africa/El_Aaiun” “Africa/Freetown” “Africa/Gaborone”
[25] “Africa/Harare” “Africa/Johannesburg” “Africa/Juba” “Africa/Kampala”
[29] “Africa/Khartoum” “Africa/Kigali” “Africa/Kinshasa” “Africa/Lagos”
[33] “Africa/Libreville” “Africa/Lome” “Africa/Luanda” “Africa/Lubumbashi”
[37] “Africa/Lusaka” “Africa/Malabo” “Africa/Maputo” “Africa/Maseru”
[41] “Africa/Mbabane” “Africa/Mogadishu” “Africa/Monrovia” “Africa/Nairobi”
[45] “Africa/Ndjamena” “Africa/Niamey” “Africa/Nouakchott” “Africa/Ouagadougou”
[49] “Africa/Porto-Novo” “Africa/Sao_Tome” “Africa/Timbuktu” “Africa/Tripoli”
[53] “Africa/Tunis” “Africa/Windhoek” “America/Adak” “America/Anchorage”
[57] “America/Anguilla” “America/Antigua” “America/Araguaina” “America/Argentina/Buenos_Aires”
[61] “America/Argentina/Catamarca” “America/Argentina/ComodRivadavia” “America/Argentina/Cordoba” “America/Argentina/Jujuy”
[65] “America/Argentina/La_Rioja” “America/Argentina/Mendoza” “America/Argentina/Rio_Gallegos” “America/Argentina/Salta”
[69] “America/Argentina/San_Juan” “America/Argentina/San_Luis” “America/Argentina/Tucuman” “America/Argentina/Ushuaia”
[73] “America/Aruba” “America/Asuncion” “America/Atikokan” “America/Atka”
[77] “America/Bahia” “America/Bahia_Banderas” “America/Barbados” “America/Belem”
[81] “America/Belize” “America/Blanc-Sablon” “America/Boa_Vista” “America/Bogota”
[85] “America/Boise” “America/Buenos_Aires” “America/Cambridge_Bay” “America/Campo_Grande”
[89] “America/Cancun” “America/Caracas” “America/Catamarca” “America/Cayenne”
[93] “America/Cayman” “America/Chicago” “America/Chihuahua” “America/Coral_Harbour”
[97] “America/Cordoba” “America/Costa_Rica” “America/Creston” “America/Cuiaba”
[101] “America/Curacao” “America/Danmarkshavn” “America/Dawson” “America/Dawson_Creek”
[105] “America/Denver” “America/Detroit” “America/Dominica” “America/Edmonton”
[109] “America/Eirunepe” “America/El_Salvador” “America/Ensenada” “America/Fort_Nelson”
[113] “America/Fort_Wayne” “America/Fortaleza” “America/Glace_Bay” “America/Godthab”
[117] “America/Goose_Bay” “America/Grand_Turk” “America/Grenada” “America/Guadeloupe”
[121] “America/Guatemala” “America/Guayaquil” “America/Guyana” “America/Halifax”
[125] “America/Havana” “America/Hermosillo” “America/Indiana/Indianapolis” “America/Indiana/Knox”
[129] “America/Indiana/Marengo” “America/Indiana/Petersburg” “America/Indiana/Tell_City” “America/Indiana/Vevay”
[133] “America/Indiana/Vincennes” “America/Indiana/Winamac” “America/Indianapolis” “America/Inuvik”
[137] “America/Iqaluit” “America/Jamaica” “America/Jujuy” “America/Juneau”
[141] “America/Kentucky/Louisville” “America/Kentucky/Monticello” “America/Knox_IN” “America/Kralendijk”
[145] “America/La_Paz” “America/Lima” “America/Los_Angeles” “America/Louisville”
[149] “America/Lower_Princes” “America/Maceio” “America/Managua” “America/Manaus”
[153] “America/Marigot” “America/Martinique” “America/Matamoros” “America/Mazatlan”
[157] “America/Mendoza” “America/Menominee” “America/Merida” “America/Metlakatla”
[161] “America/Mexico_City” “America/Miquelon” “America/Moncton” “America/Monterrey”
[165] “America/Montevideo” “America/Montreal” “America/Montserrat” “America/Nassau”
[169] “America/New_York” “America/Nipigon” “America/Nome” “America/Noronha”
[173] “America/North_Dakota/Beulah” “America/North_Dakota/Center” “America/North_Dakota/New_Salem” “America/Ojinaga”
[177] “America/Panama” “America/Pangnirtung” “America/Paramaribo” “America/Phoenix”
[181] “America/Port_of_Spain” “America/Port-au-Prince” “America/Porto_Acre” “America/Porto_Velho”
[185] “America/Puerto_Rico” “America/Punta_Arenas” “America/Rainy_River” “America/Rankin_Inlet”
[189] “America/Recife” “America/Regina” “America/Resolute” “America/Rio_Branco”
[193] “America/Rosario” “America/Santa_Isabel” “America/Santarem” “America/Santiago”
[197] “America/Santo_Domingo” “America/Sao_Paulo” “America/Scoresbysund” “America/Shiprock”
[201] “America/Sitka” “America/St_Barthelemy” “America/St_Johns” “America/St_Kitts”
[205] “America/St_Lucia” “America/St_Thomas” “America/St_Vincent” “America/Swift_Current”
[209] “America/Tegucigalpa” “America/Thule” “America/Thunder_Bay” “America/Tijuana”
[213] “America/Toronto” “America/Tortola” “America/Vancouver” “America/Virgin”
[217] “America/Whitehorse” “America/Winnipeg” “America/Yakutat” “America/Yellowknife”
[221] “Antarctica/Casey” “Antarctica/Davis” “Antarctica/DumontDUrville” “Antarctica/Macquarie”
[225] “Antarctica/Mawson” “Antarctica/McMurdo” “Antarctica/Palmer” “Antarctica/Rothera”
[229] “Antarctica/South_Pole” “Antarctica/Syowa” “Antarctica/Troll” “Antarctica/Vostok”
[233] “Arctic/Longyearbyen” “Asia/Aden” “Asia/Almaty” “Asia/Amman”
[237] “Asia/Anadyr” “Asia/Aqtau” “Asia/Aqtobe” “Asia/Ashgabat”
[241] “Asia/Ashkhabad” “Asia/Atyrau” “Asia/Baghdad” “Asia/Bahrain”
[245] “Asia/Baku” “Asia/Bangkok” “Asia/Barnaul” “Asia/Beirut”
[249] “Asia/Bishkek” “Asia/Brunei” “Asia/Calcutta” “Asia/Chita”
[253] “Asia/Choibalsan” “Asia/Chongqing” “Asia/Chungking” “Asia/Colombo”
[257] “Asia/Dacca” “Asia/Damascus” “Asia/Dhaka” “Asia/Dili”
[261] “Asia/Dubai” “Asia/Dushanbe” “Asia/Famagusta” “Asia/Gaza”
[265] “Asia/Harbin” “Asia/Hebron” “Asia/Ho_Chi_Minh” “Asia/Hong_Kong”
[269] “Asia/Hovd” “Asia/Irkutsk” “Asia/Istanbul” “Asia/Jakarta”
[273] “Asia/Jayapura” “Asia/Jerusalem” “Asia/Kabul” “Asia/Kamchatka”
[277] “Asia/Karachi” “Asia/Kashgar” “Asia/Kathmandu” “Asia/Katmandu”
[281] “Asia/Khandyga” “Asia/Kolkata” “Asia/Krasnoyarsk” “Asia/Kuala_Lumpur”
[285] “Asia/Kuching” “Asia/Kuwait” “Asia/Macao” “Asia/Macau”
[289] “Asia/Magadan” “Asia/Makassar” “Asia/Manila” “Asia/Muscat”
[293] “Asia/Nicosia” “Asia/Novokuznetsk” “Asia/Novosibirsk” “Asia/Omsk”
[297] “Asia/Oral” “Asia/Phnom_Penh” “Asia/Pontianak” “Asia/Pyongyang”
[301] “Asia/Qatar” “Asia/Qyzylorda” “Asia/Rangoon” “Asia/Riyadh”
[305] “Asia/Saigon” “Asia/Sakhalin” “Asia/Samarkand” “Asia/Seoul”
[309] “Asia/Shanghai” “Asia/Singapore” “Asia/Srednekolymsk” “Asia/Taipei”
[313] “Asia/Tashkent” “Asia/Tbilisi” “Asia/Tehran” “Asia/Tel_Aviv”
[317] “Asia/Thimbu” “Asia/Thimphu” “Asia/Tokyo” “Asia/Tomsk”
[321] “Asia/Ujung_Pandang” “Asia/Ulaanbaatar” “Asia/Ulan_Bator” “Asia/Urumqi”
[325] “Asia/Ust-Nera” “Asia/Vientiane” “Asia/Vladivostok” “Asia/Yakutsk”
[329] “Asia/Yangon” “Asia/Yekaterinburg” “Asia/Yerevan” “Atlantic/Azores”
[333] “Atlantic/Bermuda” “Atlantic/Canary” “Atlantic/Cape_Verde” “Atlantic/Faeroe”
[337] “Atlantic/Faroe” “Atlantic/Jan_Mayen” “Atlantic/Madeira” “Atlantic/Reykjavik”
[341] “Atlantic/South_Georgia” “Atlantic/St_Helena” “Atlantic/Stanley” “Australia/ACT”
[345] “Australia/Adelaide” “Australia/Brisbane” “Australia/Broken_Hill” “Australia/Canberra”
[349] “Australia/Currie” “Australia/Darwin” “Australia/Eucla” “Australia/Hobart”
[353] “Australia/LHI” “Australia/Lindeman” “Australia/Lord_Howe” “Australia/Melbourne”
[357] “Australia/North” “Australia/NSW” “Australia/Perth” “Australia/Queensland”
[361] “Australia/South” “Australia/Sydney” “Australia/Tasmania” “Australia/Victoria”
[365] “Australia/West” “Australia/Yancowinna” “Brazil/Acre” “Brazil/DeNoronha”
[369] “Brazil/East” “Brazil/West” “Canada/Atlantic” “Canada/Central”
[373] “Canada/Eastern” “Canada/Mountain” “Canada/Newfoundland” “Canada/Pacific”
[377] “Canada/Saskatchewan” “Canada/Yukon” “CET” “Chile/Continental”
[381] “Chile/EasterIsland” “CST6CDT” “Cuba” “EET”
[385] “Egypt” “Eire” “EST” “EST5EDT”
[389] “Etc/GMT” “Etc/GMT-0” “Etc/GMT-1” “Etc/GMT-10”
[393] “Etc/GMT-11” “Etc/GMT-12” “Etc/GMT-13” “Etc/GMT-14”
[397] “Etc/GMT-2” “Etc/GMT-3” “Etc/GMT-4” “Etc/GMT-5”
[401] “Etc/GMT-6” “Etc/GMT-7” “Etc/GMT-8” “Etc/GMT-9”
[405] “Etc/GMT+0” “Etc/GMT+1” “Etc/GMT+10” “Etc/GMT+11”
[409] “Etc/GMT+12” “Etc/GMT+2” “Etc/GMT+3” “Etc/GMT+4”
[413] “Etc/GMT+5” “Etc/GMT+6” “Etc/GMT+7” “Etc/GMT+8”
[417] “Etc/GMT+9” “Etc/GMT0” “Etc/Greenwich” “Etc/UCT”
[421] “Etc/Universal” “Etc/UTC” “Etc/Zulu” “Europe/Amsterdam”
[425] “Europe/Andorra” “Europe/Astrakhan” “Europe/Athens” “Europe/Belfast”
[429] “Europe/Belgrade” “Europe/Berlin” “Europe/Bratislava” “Europe/Brussels”
[433] “Europe/Bucharest” “Europe/Budapest” “Europe/Busingen” “Europe/Chisinau”
[437] “Europe/Copenhagen” “Europe/Dublin” “Europe/Gibraltar” “Europe/Guernsey”
[441] “Europe/Helsinki” “Europe/Isle_of_Man” “Europe/Istanbul” “Europe/Jersey”
[445] “Europe/Kaliningrad” “Europe/Kiev” “Europe/Kirov” “Europe/Lisbon”
[449] “Europe/Ljubljana” “Europe/London” “Europe/Luxembourg” “Europe/Madrid”
[453] “Europe/Malta” “Europe/Mariehamn” “Europe/Minsk” “Europe/Monaco”
[457] “Europe/Moscow” “Europe/Nicosia” “Europe/Oslo” “Europe/Paris”
[461] “Europe/Podgorica” “Europe/Prague” “Europe/Riga” “Europe/Rome”
[465] “Europe/Samara” “Europe/San_Marino” “Europe/Sarajevo” “Europe/Saratov”
[469] “Europe/Simferopol” “Europe/Skopje” “Europe/Sofia” “Europe/Stockholm”
[473] “Europe/Tallinn” “Europe/Tirane” “Europe/Tiraspol” “Europe/Ulyanovsk”
[477] “Europe/Uzhgorod” “Europe/Vaduz” “Europe/Vatican” “Europe/Vienna”
[481] “Europe/Vilnius” “Europe/Volgograd” “Europe/Warsaw” “Europe/Zagreb”
[485] “Europe/Zaporozhye” “Europe/Zurich” “GB” “GB-Eire”
[489] “GMT” “GMT-0” “GMT+0” “GMT0”
[493] “Greenwich” “Hongkong” “HST” “Iceland”
[497] “Indian/Antananarivo” “Indian/Chagos” “Indian/Christmas” “Indian/Cocos”
[501] “Indian/Comoro” “Indian/Kerguelen” “Indian/Mahe” “Indian/Maldives”
[505] “Indian/Mauritius” “Indian/Mayotte” “Indian/Reunion” “Iran”
[509] “Israel” “Jamaica” “Japan” “Kwajalein”
[513] “Libya” “MET” “Mexico/BajaNorte” “Mexico/BajaSur”
[517] “Mexico/General” “MST” “MST7MDT” “Navajo”
[521] “NZ” “NZ-CHAT” “Pacific/Apia” “Pacific/Auckland”
[525] “Pacific/Bougainville” “Pacific/Chatham” “Pacific/Chuuk” “Pacific/Easter”
[529] “Pacific/Efate” “Pacific/Enderbury” “Pacific/Fakaofo” “Pacific/Fiji”
[533] “Pacific/Funafuti” “Pacific/Galapagos” “Pacific/Gambier” “Pacific/Guadalcanal”
[537] “Pacific/Guam” “Pacific/Honolulu” “Pacific/Johnston” “Pacific/Kiritimati”
[541] “Pacific/Kosrae” “Pacific/Kwajalein” “Pacific/Majuro” “Pacific/Marquesas”
[545] “Pacific/Midway” “Pacific/Nauru” “Pacific/Niue” “Pacific/Norfolk”
[549] “Pacific/Noumea” “Pacific/Pago_Pago” “Pacific/Palau” “Pacific/Pitcairn”
[553] “Pacific/Pohnpei” “Pacific/Ponape” “Pacific/Port_Moresby” “Pacific/Rarotonga”
[557] “Pacific/Saipan” “Pacific/Samoa” “Pacific/Tahiti” “Pacific/Tarawa”
[561] “Pacific/Tongatapu” “Pacific/Truk” “Pacific/Wake” “Pacific/Wallis”
[565] “Pacific/Yap” “Poland” “Portugal” “PRC”
[569] “PST8PDT” “ROC” “ROK” “Singapore”
[573] “Turkey” “UCT” “Universal” “US/Alaska”
[577] “US/Aleutian” “US/Arizona” “US/Central” “US/East-Indiana”
[581] “US/Eastern” “US/Hawaii” “US/Indiana-Starke” “US/Michigan”
[585] “US/Mountain” “US/Pacific” “US/Pacific-New” “US/Samoa”
[589] “UTC” “W-SU” “WET” “Zulu”

Last but not least, let’s learn how to do arithmetic with dates and times (and quite personally, I think this is tons of fun):

The lubridate packages contains two general time span classes-durations and periods. To create a function for periods, simply use the plural form for the unit of time you wish to make a period from. To create a function for durations, use the formatting for periods functions, but add a d in front of the unit of time.

In the hours() function, the amount of hours, minutes and seconds are displayed; since I used 15 for hours, the period is shown as 15H 0M 0S. In the dhours() function, the amount of hours are converted into seconds; since I also used 15 for hours, the duration shown is 54000s.

What if we used decimals for our period and duration functions? Let’s see what would happen:

In this example, I used 15.5 hours for both my period and duration functions. While 15.5 worked fine with my duration function, it gave me an error when I tried to use it with my period function because the parameter for a period function must be an integer.

The period function will give you the entire time period down to the second, while the duration function will always give you the length of the time period in seconds.

  • I’m not sure how far the duration function would go, but I did try using dmonth and got an error.

Why are there two classes of time in lubridate? This is because the calendar timeline isn’t as reliable as the number line. See, durations always supply mathematically precise results-a duration year is ALWAYS 365 days (even for a leap year like 2020). However, periods fluctuate the way the calendar timeline does, so in periods, 2019 has 365 days while 2020 has 366 days.

But, before I get into any further time-date arithmetic, let’s see how R can detect a leap year:

To find out whether a year is a leap year, simply use the leap_year() function along with the year you want to inquire about as the parameter. If the result is FALSE, the year isn’t a leap year, but if it’s TRUE, then the year is a leap year. As you can see, 2018 and 2019 aren’t leap years, but 2020 is a leap year.

Now, let’s perform some basic addition with period years and duration years:

When I add 1 period year and 1 duration year to the date January 1 2019, I get January 1 2020 both times. This is because 2019 has 365 days, so 1 period year and 1 duration year from January 1 2019 would add up to January 1 2020.

However, with a leap year like 2020, the results from period years and duration years would be different. Similar to the last example, I am adding 1 period year and 1 duration year to January 1 2020. Since period years fluctuate with the calendar timeline, 1 period year from January 1 2020 is January 1 2021. However, 1 duration year from January 1 2020 is December 1 2020, since duration years always contain 365 days (and 2020 has 366 days).

Aside from adding period years and duration years, you can also perform other arithmetic with other units of time (such as days and months);

In the first expression shown, I added 1 month to the date May 3 2020 and got June 3 2020. In the second expression, I subtracted 18 days from May 3 2020 and got April 15 2020.

Now, here’s where things get interesting. Notice how the third and fourth expressions shown generated error messages. This is because, unlike with regular numbers and decimals, you can’t multiply or divide units of time.

  • If you can’t multiply or divide units of time, then you certainly can’t do more advanced things like raising a date to a certain power or find the base-10 logarithm of a certain date (just saying in case anyone was wondering).

Now, there’s something interesting I wanted to point out when it comes to adding months to dates. In the example, when I added 1 month to May 3 2020, I got June 3 2020. Seems clear enough, right? Well, not always. See, there are two possible answers to adding a month to May 3 2020. They are:

  • June 3 2020, which is 31 days after May 3 2020
  • May 31 2020, which is 4 weeks after May 3 2020 (four weeks is considered a month)

I’ll explain the whole month addition thing later, but now, let’s discuss how to calculate the duration between two dates. To do this, we must first create a date interval:

To create an interval, use the interval function that lubridate provides. For the parameters, use two dates-and keep the second date greater than the first date.

  • You can also include date-time objects as parameters in interval, complete with time-zones. I just chose not to include them for simplicity’s sake.

I’m going to use my most recent holiday vacation for this example, which lasted from December 24 2019 to January 5 2020. I stored my interval in the variable vacation.

Now, how long was my holiday vacation in days?:

Dividing the vacation variable by ddays(1) gives us the length of my vacation in days-12. To be sure we get the exact duration in days, I had to use 1 as the parameter for ddays, because if I had used another number, I wouldn’t have gotten the exact duration. For instance, I tried vacation/ddays(2), and got 6, which is half the duration of my vacation (in days).

  • I could’ve used days(1) instead of ddays(1) and I would’ve gotten the same answer-12.

Now here’s another example of an interval:

This interval represents how long I’ve been living in Nashville as of May 3 2020. 09052019 is the first parameter, since I moved to Nashville on September 5 2019.

Now how long is that in days and months?:

So, according to these calculations, I’ve been living in Nashville for 241 days, or 7.93 months as of May 3 2020. What I find interesting is that the days and ddays functions both returned 241, despite having a February 29 factored in.

Now let’s try an even larger time interval:

This interval represents how long this blog has been active for as of May 3 2020 (I launched this blog on June 13 2018). So how long would this be in years, months, and days?:

All in all, this blog has been active for:

  • 1.888 period years and 1.89 duration years.
  • 22.67 months
  • 690 days (both period days and duration days)

Personally, I think it’s interesting that dyears and ddays can be used, but not dmonths. But I guess it’s just one of those R quirks.

Last but not least, let’s discuss the whole adding months thing. Earlier in this post, I did mention there were several possible answers to adding a month (or months) to a certain time using the example of May 3 2020. In that example, I said that there were two possible answers to the question of adding a month-June 3 (31 days from May 3) or May 31 (four weeks from May 3). See, since the 12 months of the year aren’t equal length, trying to do arithmetic with them won’t work.

So, how would we approach this problem? Let’s take a look:

In this example, the months function keeps adding a month to 04302020 (April 30 2020) 11 times. You can see the results of the months function in the output below; the first result is 2020-04-30 and the last result is 2021-03-30, which is 11 months from the start date.

But wait, what’s the NA doing there? See, since there’s no such date as February 30 2021, an NA is displayed in its place.

  • The syntax for the months functions is as follows-months(X months from date:Y months from X). This means that the value to the left of the colon should be how many months from the start date you want to begin the calculation at and the value to the right of the colon should be how many months from the first value you want the calculations to end at.
  • It’s not necessary to use 0 as the first value for the months function, but if you want to include the given date in your calculation, then use 0.

OK, so what if we didn’t want to see any NA values. Here’s how we’d approach that:

The floor_date function automatically starts the calculations on the first of the month following the date given (since I gave 05032020 as the date, the calculations automatically start with June 1 2020). The months function will add 1 month to June 1 2020 11 times and display all 12 of these results (the 12 results include June 1 2020). The days function tells R to run under the assumption that each month has 31 days (though using 28 for days would’ve worked just fine too).

OK, so there’s another approach to the whole adding-a-month-to-a-date-several-times question. Here it is:

Using the %m+% and %m-% operators, you can get a list of months up to X months out from a certain date. The amazing thing about these operators is that they will automatically roll back to the last day of the month if necessary.

One thing to keep in mind is that the %m+% operator will move forward 1 month for X amount of months but the %m-% operator will move backwards 1 month for X amount of months. At least both are very precise when calculating months.