Skip to content

Commit

Permalink
Move calendar initialization to server startup (#5037)
Browse files Browse the repository at this point in the history
  • Loading branch information
devinrsmith authored Jan 16, 2024
1 parent 110449d commit 51546a5
Show file tree
Hide file tree
Showing 17 changed files with 224 additions and 106 deletions.
1 change: 1 addition & 0 deletions Integrations/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ dependencies {
implementation project(':log-factory')

testImplementation project(':engine-test-utils')
testImplementation TestTools.projectDependency(project, 'engine-time')

testRuntimeOnly project(':log-to-slf4j')
// add configs, and some runtime dependencies to test classpaths
Expand Down
1 change: 1 addition & 0 deletions Plot/Plot.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ dependencies {

testImplementation TestTools.projectDependency(project, 'Util')
testImplementation TestTools.projectDependency(project, 'engine-table')
testImplementation TestTools.projectDependency(project, 'engine-time')

testRuntimeOnly project(path: ':configs')
testRuntimeOnly project(path: ':test-configs')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
*/
package io.deephaven.plot.axistransformations;

import io.deephaven.base.testing.BaseArrayTestCase;
import io.deephaven.time.DateTimeUtils;
import io.deephaven.time.calendar.CalendarInit;
import io.deephaven.time.calendar.Calendars;
import junit.framework.TestCase;

import java.nio.file.Paths;
import java.time.Instant;
import java.time.ZoneId;
import java.util.Objects;

public class TestAxisTransformBusinessCalendar extends BaseArrayTestCase {
public class TestAxisTransformBusinessCalendar extends TestCase {

private static final ZoneId TZ_JP = ZoneId.of("Asia/Tokyo");

Expand Down Expand Up @@ -41,6 +42,7 @@ public class TestAxisTransformBusinessCalendar extends BaseArrayTestCase {

@Override
public void setUp() throws Exception {
CalendarInit.init();
final String path = Paths
.get(Objects.requireNonNull(TestAxisTransformBusinessCalendar.class.getResource("/JPOSE.calendar"))
.toURI())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
package io.deephaven.plot.axistransformations;

import io.deephaven.time.calendar.BusinessCalendar;
import io.deephaven.time.calendar.CalendarInit;
import io.deephaven.time.calendar.Calendars;
import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;
Expand All @@ -28,6 +30,11 @@ public class TestAxisTransforms {
final double d9 = -d4;
private final double delta = 0.00001;

@Before
public void setUp() {
CalendarInit.init();
}

@Test
public void testLog() {
final AxisTransform transform = AxisTransforms.LOG;
Expand Down
1 change: 1 addition & 0 deletions engine/time/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dependencies {
implementation project(':Configuration')
implementation project(':log-factory')
implementation depJdom2
Classpaths.inheritDagger(project)

testImplementation TestTools.projectDependency(project, 'Base')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ private YearData getYearData(final int year) {
* is different from the schedule for a standard business day or weekend.
* @throws RequirementFailure if any argument is null.
*/
BusinessCalendar(final String name, final String description, final ZoneId timeZone,
public BusinessCalendar(final String name, final String description, final ZoneId timeZone,
final LocalDate firstValidDate, final LocalDate lastValidDate,
final CalendarDay<LocalTime> standardBusinessDay, final Set<DayOfWeek> weekendDays,
final Map<LocalDate, CalendarDay<Instant>> holidays) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,18 @@
import org.jdom2.input.SAXBuilder;
import org.jetbrains.annotations.NotNull;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.time.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
* A parser for reading business calendar XML files.
*
* <p>
* Business calendar XML files should be formatted as:
*
* <pre>
Expand Down Expand Up @@ -56,14 +59,14 @@
*
* In addition, legacy XML files are supported. These files have dates formatted as `yyyyMMdd` instead of ISO-8601
* `yyy-MM-dd`. Additionally, legacy uses `businessPeriod` tags in place of the `businessTime` tags.
*
*
* <pre>
* {@code
* <!-- Current format -->
* <businessTime><open>09:30</open><close>16:00</close></businessTime>
* }
* </pre>
*
*
* <pre>
* {@code
* <!-- Legacy format -->
Expand All @@ -73,7 +76,7 @@
*
* The legacy format may be deprecated in a future release.
*/
class BusinessCalendarXMLParser {
public final class BusinessCalendarXMLParser {

private static class BusinessCalendarInputs {
private String calendarName;
Expand Down Expand Up @@ -108,42 +111,82 @@ public static BusinessCalendar loadBusinessCalendar(@NotNull final String file)
public static BusinessCalendar loadBusinessCalendar(@NotNull final File file) {
Require.neqNull(file, "file");
final BusinessCalendarInputs in = parseBusinessCalendarInputs(file);
return new BusinessCalendar(in.calendarName, in.description,
in.timeZone, in.firstValidDate, in.lastValidDate,
in.standardBusinessDay, in.weekendDays, in.holidays);
}

/**
* Loads a business calendar from an XML input stream.
*
* @param inputStream XML input stream
* @return business calendar.
* @throws RequirementFailure if the input is null
*/
public static BusinessCalendar loadBusinessCalendar(@NotNull final InputStream inputStream) {
Require.neqNull(inputStream, "inputStream");
final BusinessCalendarInputs in = parseBusinessCalendarInputs(inputStream);
return new BusinessCalendar(in.calendarName, in.description,
in.timeZone, in.firstValidDate, in.lastValidDate,
in.standardBusinessDay, in.weekendDays, in.holidays);
}

/**
* Loads a business calendar from an XML resource.
*
* @param resource XML input stream
* @return business calendar.
*/
public static BusinessCalendar loadBusinessCalendarFromResource(String resource) throws IOException {
final InputStream in = Calendars.class.getResourceAsStream(resource);
if (in == null) {
throw new RuntimeException("Could not open resource " + resource + " from classpath");
}
try (final InputStream bin = new BufferedInputStream(in)) {
return loadBusinessCalendar(bin);
}
}

private static BusinessCalendarInputs parseBusinessCalendarInputs(@NotNull final File file) {
Require.neqNull(file, "file");
try {
final BusinessCalendarInputs calendarElements = new BusinessCalendarInputs();

Element root = loadXMLRootElement(file);
calendarElements.calendarName = getText(getRequiredChild(root, "name"));
calendarElements.timeZone = TimeZoneAliases.zoneId(getText(getRequiredChild(root, "timeZone")));
calendarElements.description = getText(root.getChild("description"));
calendarElements.holidays = parseHolidays(root, calendarElements.timeZone);
final String firstValidDateStr = getText(root.getChild("firstValidDate"));
calendarElements.firstValidDate =
firstValidDateStr == null ? Collections.min(calendarElements.holidays.keySet())
: DateTimeUtils.parseLocalDate(firstValidDateStr);
final String lastValidDateStr = getText(root.getChild("lastValidDate"));
calendarElements.lastValidDate =
lastValidDateStr == null ? Collections.max(calendarElements.holidays.keySet())
: DateTimeUtils.parseLocalDate(lastValidDateStr);

// Set the default values
final Element defaultElement = getRequiredChild(root, "default");
calendarElements.weekendDays = parseWeekendDays(defaultElement);
calendarElements.standardBusinessDay = parseCalendarDaySchedule(defaultElement);

return calendarElements;
return fill(loadXMLRootElement(file));
} catch (Exception e) {
throw new RuntimeException("Unable to load calendar file: file=" + file.getPath(), e);
}
}

private static BusinessCalendarInputs parseBusinessCalendarInputs(@NotNull final InputStream in) {
Require.neqNull(in, "in");
try {
return fill(loadXMLRootElement(in));
} catch (Exception e) {
throw new RuntimeException("Unable to load calendar file: inputStream=" + in, e);
}
}

private static BusinessCalendarInputs fill(Element root) throws Exception {
final BusinessCalendarInputs calendarElements = new BusinessCalendarInputs();
calendarElements.calendarName = getText(getRequiredChild(root, "name"));
calendarElements.timeZone = TimeZoneAliases.zoneId(getText(getRequiredChild(root, "timeZone")));
calendarElements.description = getText(root.getChild("description"));
calendarElements.holidays = parseHolidays(root, calendarElements.timeZone);
final String firstValidDateStr = getText(root.getChild("firstValidDate"));
calendarElements.firstValidDate =
firstValidDateStr == null ? Collections.min(calendarElements.holidays.keySet())
: DateTimeUtils.parseLocalDate(firstValidDateStr);
final String lastValidDateStr = getText(root.getChild("lastValidDate"));
calendarElements.lastValidDate =
lastValidDateStr == null ? Collections.max(calendarElements.holidays.keySet())
: DateTimeUtils.parseLocalDate(lastValidDateStr);

// Set the default values
final Element defaultElement = getRequiredChild(root, "default");
calendarElements.weekendDays = parseWeekendDays(defaultElement);
calendarElements.standardBusinessDay = parseCalendarDaySchedule(defaultElement);
return calendarElements;
}

private static Element loadXMLRootElement(File calendarFile) throws Exception {
final Document doc;

Expand All @@ -159,6 +202,21 @@ private static Element loadXMLRootElement(File calendarFile) throws Exception {
return doc.getRootElement();
}

private static Element loadXMLRootElement(InputStream in) throws Exception {
final Document doc;

try {
final SAXBuilder builder = new SAXBuilder();
doc = builder.build(in);
} catch (JDOMException e) {
throw new Exception("Error parsing business calendar: inputStream=" + in, e);
} catch (IOException e) {
throw new Exception("Error loading business calendar: inputStream=" + in, e);
}

return doc.getRootElement();
}

private static Element getRequiredChild(@NotNull final Element root, final String child) throws Exception {
Element element = root.getChild(child);
if (element != null) {
Expand Down
Loading

0 comments on commit 51546a5

Please sign in to comment.