Work with calendars

This guide shows you how to create and use business calendars in Deephaven. A business calendar is a calendar that knows which days and hours are business time and which are not, such as weekends, holidays, and hours outside business hours. Each calendar is a BusinessCalendar object. These calendars are useful in table operations, such as filtering to business hours or counting business days.

The static methods of the Calendars class let you:

This guide uses the methods that list, get, and add calendars. See Related documentation for the others.

Get a calendar

The code block below uses calendarNames to list the available calendars and calendar to get the USNYSE_EXAMPLE calendar.

Deephaven comes with three calendars: UTC, USNYSE_EXAMPLE, and USBANK_EXAMPLE. The output also shows that nyseCal is an io.deephaven.time.calendar.BusinessCalendar object. The sections below use its methods in queries.

Warning

The calendars that come with Deephaven are examples, and Deephaven doesn't guarantee that their holidays are complete or current. Create your own calendars for production use.

Use a calendar in queries

The examples in this section call methods on nyseCal, the calendar from Get a calendar, and use the source table created below.

Create data

Before you use a calendar in queries, create a table with some data. The following code block creates about three weeks' worth of date-time data spaced 3 minutes apart.

Input data types

Date and time arguments to BusinessCalendar methods are Java date-time types such as Instant, ZonedDateTime, and LocalDate. Many methods also accept strings. Check the Javadoc for each method's overloads. For example, isBusinessTime accepts an Instant or a ZonedDateTime, but not a string or a LocalDate.

See Time in Deephaven for conversion functions. The examples below use date-time literals in query strings, which Deephaven converts to Instant values.

Business days and business time

The following example uses numberBusinessDates and numberNonBusinessDates to calculate the number of business days and non-business days (weekends and holidays) between two timestamps. Both counts include the start and end dates.

The following code block filters source twice. The first filter uses isBusinessDay to keep rows that fall on an NYSE business day. The second uses isBusinessTime to keep rows that fall within NYSE business hours.

Plot against business time

To plot data against business time, call xBusinessTime with the calendar on a plot. The plot's x-axis leaves out weekends, holidays, and hours outside business hours, so the plot has no gaps where the market is closed. The following code block plots all of source against NYSE business time.

Create a calendar

Deephaven's built-in calendar files use XML to define the properties of the calendar, which include:

  • Name
  • Time zone
  • Description
  • Valid date range
  • Default business hours and weekend days
  • Holidays and half-days

Deephaven ignores other elements, such as <language> and <country>.

To build your own calendar, create a calendar file in the format that the BusinessCalendarXMLParser Javadoc describes. The rest of this guide goes over an example of using a custom-built calendar for a hypothetical business for the year 2024. The example is based on a calendar file in Deephaven's examples repository.

The calendar file

Most business calendars have a single business period each day, such as 9am to 5pm. Some split the day around a lunch break. The test calendar below covers only 2024 and defines:

  • Two business periods: 8am to 12pm and 1pm to 5pm.
  • The 2024 holidays, two of which are half-days that are open only for the morning period.

Save the listing as /data/examples/Calendar/TestCalendar_2024.calendar in the Deephaven Docker container. The examples below load the calendar from that path.

If you have the examples repository's copy of TestCalendar_2024.calendar, replace it. That copy puts both <open>/<close> pairs in one <businessTime> element. Deephaven reads only the first pair in each element, so the copy defines only the morning period. The listing below gives each period its own <businessTime> element.

Test calendar for 2024

Add and use the new calendar

Add the calendar to the set of available calendars

Add a calendar from a running session with addCalendarFromFile, or load it when the server starts.

The following code block uses addCalendarFromFile to load /data/examples/Calendar/TestCalendar_2024.calendar, the file you saved in The calendar file.

Get an instance of the new calendar

After you add the calendar, get it by the name in its <name> element, the same way as a built-in calendar. calendar matches the name case-insensitively. calendarNames lists names in uppercase, such as TESTCALENDAR_2024.

Use the new calendar in a query

The new calendar works in queries the same way as nyseCal in Use a calendar in queries. The following code block keeps only the rows of the source table from Create data that fall within the test calendar's business hours. Because of the lunch break, the result has no rows between 12pm and 1pm. It also has no rows on the January 1 and January 15 holidays.

Load calendars when the server starts

Instead of calling addCalendarFromFile in each session, you can load calendars when the server starts. The configuration property Calendar.userImportPath adds calendars to the built-in set when the server starts. Its value is the location of a text file that lists one calendar file location per line. Deephaven loads the text file and each calendar file as classpath resources, not filesystem paths, so:

  • The folder that holds the files must be on the server's classpath, the list of directories the Java server searches for resources. The Docker example below adds it with EXTRA_CLASSPATH.
  • Each location, including the property's value, starts with / and is relative to that folder.

Say a calendars folder next to your docker-compose.yml file contains three calendar files: MyCalendar.calendar, TestCalendar_2024.calendar, and CrazyCalendar.calendar. The same folder also contains a text file named calendar_imports.txt, which looks as follows:

To load these calendars when the server starts with Docker Compose, mount the folder, add it to the classpath with EXTRA_CLASSPATH, and set the property as a JVM argument in START_OPTS:

You can also set Calendar.userImportPath in a configuration file instead of START_OPTS. The folder must still be on the classpath.

Caution

Don't set Calendar.importPath to load your own calendars. Use Calendar.userImportPath instead. Calendar.importPath points to the list of built-in calendars, so overriding it drops UTC, USNYSE_EXAMPLE, and USBANK_EXAMPLE unless your list includes them.

The Calendar.default property sets the default calendar, and its value is UTC unless you change it. If UTC isn't loaded, the Groovy console session fails to start, because its startup script requests the default calendar and gets a "No such calendar" error. If you drop UTC, also set Calendar.default to a calendar you load.