diff --git a/cwms-data-api/src/main/java/cwms/cda/api/LevelsController.java b/cwms-data-api/src/main/java/cwms/cda/api/LevelsController.java index a50fb151a..557dbb4bd 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/LevelsController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/LevelsController.java @@ -75,7 +75,7 @@ import java.nio.charset.StandardCharsets; import java.time.Instant; import java.time.ZoneId; -import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -124,6 +124,12 @@ public void create(@NotNull Context ctx) { LocationLevel level = deserializeLocationLevel(ctx); level.validate(); + if (!LocationLevel.truncateDate(level.getLevelDate()).equals(level.getLevelDate())) { + Map errorDetails = new HashMap<>(); + errorDetails.put("message", "Level effective date cannot have seconds"); + throw new BadRequestResponse("", errorDetails); + } + DSLContext dsl = getDslContext(ctx); LocationLevelsDao levelsDao = getLevelsDao(dsl); levelsDao.storeLocationLevel(level); diff --git a/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/LocationLevel.java b/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/LocationLevel.java index 8ab3d09df..8f6b15951 100644 --- a/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/LocationLevel.java +++ b/cwms-data-api/src/main/java/cwms/cda/data/dto/locationlevel/LocationLevel.java @@ -26,14 +26,6 @@ package cwms.cda.data.dto.locationlevel; -import cwms.cda.data.dto.catalog.LocationAlias; -import java.math.BigDecimal; -import java.time.Instant; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -47,6 +39,7 @@ import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import cwms.cda.data.dto.CwmsDTO; import cwms.cda.data.dto.CwmsDTOValidator; +import cwms.cda.data.dto.catalog.LocationAlias; import cwms.cda.formatters.Formats; import cwms.cda.formatters.UnsupportedFormatException; import cwms.cda.formatters.annotations.FormattableWith; @@ -54,6 +47,15 @@ import cwms.cda.formatters.json.JsonV2; import cwms.cda.formatters.xml.XMLv2; import io.swagger.v3.oas.annotations.media.Schema; +import java.math.BigDecimal; +import java.time.Instant; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; @JsonRootName("LocationLevel") @JsonDeserialize(builder = LocationLevel.Builder.class) @@ -95,7 +97,8 @@ public abstract class LocationLevel extends CwmsDTO { @Schema(description = "Units the provided levels are in") private final String levelUnitsId; - @Schema(description = "The date/time at which this location level configuration takes effect.") + @Schema(description = "The date/time at which this location level configuration takes effect. " + + "Must be limited to minute accuracy.") @JsonFormat(shape = JsonFormat.Shape.STRING) private final Instant levelDate; @@ -501,4 +504,12 @@ protected void validateInternal(CwmsDTOValidator validator) { validator.required(getLocationLevelId(), "location-level-id"); validator.required(getLevelDate(), "level-date"); } + + public static ZonedDateTime truncateDate(ZonedDateTime date) { + return date.truncatedTo(ChronoUnit.MINUTES); + } + + public static Instant truncateDate(Instant date) { + return date.truncatedTo(ChronoUnit.MINUTES); + } } diff --git a/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_constant_create.json b/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_constant_create.json index c93cca2a0..f2b2f8c50 100644 --- a/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_constant_create.json +++ b/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_constant_create.json @@ -1,7 +1,7 @@ { "constant-value": 10, "level-units-id": "ft", - "level-date": "2008-12-03T10:15:30+01:00[UTC]", + "level-date": "2008-12-03T10:15:00+01:00[UTC]", "level-comment": "Lowest Point", "interpolate-string": "F", "location-level-id": "Sacramento.Elev.Inst.0.Bottom of Inlet", diff --git a/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_seasonal_create.json b/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_seasonal_create.json index fb2588a89..b3fcc8594 100644 --- a/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_seasonal_create.json +++ b/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_seasonal_create.json @@ -11,9 +11,9 @@ } ], "level-units-id": "ft", - "level-date": "2008-12-03T10:15:30+01:00[UTC]", + "level-date": "2008-12-03T10:15:00+01:00[UTC]", "level-comment": "Lowest Point", - "interval-origin": "2008-12-03T10:15:30+01:00[UTC]", + "interval-origin": "2008-12-03T10:15:00+01:00[UTC]", "interval-months": 1, "interpolate-string": "F", "location-level-id": "Sacramento.Elev.Inst.0.Bottom of Inlet", diff --git a/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_timeseries_create.json b/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_timeseries_create.json index a2a84c832..ec4c1205a 100644 --- a/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_timeseries_create.json +++ b/cwms-data-api/src/main/resources/cwms/cda/data/levels/levels_timeseries_create.json @@ -1,7 +1,7 @@ { "seasonal-time-series-id": "Sacramento.Stage.Inst.5Minutes.0.Bottom of Inlet", "level-units-id": "ft", - "level-date": "2008-12-03T10:15:30+01:00[UTC]", + "level-date": "2008-12-03T10:15:00+01:00[UTC]", "level-comment": "Bottom of Inlet, lowest level", "interpolate-string": "F", "location-level-id": "Sacramento.Elev.Inst.0.Bottom of Inlet", diff --git a/cwms-data-api/src/test/java/cwms/cda/api/LevelsControllerTestIT.java b/cwms-data-api/src/test/java/cwms/cda/api/LevelsControllerTestIT.java index 2a967a7f1..22e7bc0c9 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/LevelsControllerTestIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/LevelsControllerTestIT.java @@ -24,6 +24,33 @@ package cwms.cda.api; +import static cwms.cda.api.Controllers.BEGIN; +import static cwms.cda.api.Controllers.EFFECTIVE_DATE; +import static cwms.cda.api.Controllers.EFFECTIVE_DATE_EXACT; +import static cwms.cda.api.Controllers.END; +import static cwms.cda.api.Controllers.FORMAT; +import static cwms.cda.api.Controllers.INCLUDE_ALIASES; +import static cwms.cda.api.Controllers.INTERVAL; +import static cwms.cda.api.Controllers.LEVEL_ID_MASK; +import static cwms.cda.api.Controllers.PAGE; +import static cwms.cda.api.Controllers.PAGE_SIZE; +import static cwms.cda.api.Controllers.START; +import static cwms.cda.api.Controllers.UNIT; +import static cwms.cda.security.ApiKeyIdentityProvider.AUTH_HEADER; +import static helpers.FloatCloseTo.floatCloseTo; +import static io.restassured.RestAssured.given; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.closeTo; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isOneOf; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + import cwms.cda.ApiServlet; import cwms.cda.data.dao.LocationCategoryDao; import cwms.cda.data.dao.LocationGroupDao; @@ -33,9 +60,9 @@ import cwms.cda.data.dto.AssignedLocation; import cwms.cda.data.dto.LocationCategory; import cwms.cda.data.dto.LocationGroup; +import cwms.cda.data.dto.TimeSeries; import cwms.cda.data.dto.locationlevel.ConstantLocationLevel; import cwms.cda.data.dto.locationlevel.LocationLevel; -import cwms.cda.data.dto.TimeSeries; import cwms.cda.data.dto.locationlevel.SeasonalLocationLevel; import cwms.cda.data.dto.locationlevel.SeasonalValueBean; import cwms.cda.data.dto.locationlevel.TimeSeriesLocationLevel; @@ -44,11 +71,24 @@ import fixtures.CwmsDataApiSetupCallback; import fixtures.MinimumSchema; import fixtures.TestAccounts; +import hec.data.RatingException; +import hec.data.cwmsRating.io.RatingSetContainer; +import hec.data.cwmsRating.io.RatingSpecContainer; import io.restassured.filter.log.LogDetail; - import io.restassured.path.json.JsonPath; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; +import java.io.IOException; +import java.sql.SQLException; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.NavigableMap; +import java.util.TreeMap; +import javax.servlet.http.HttpServletResponse; import mil.army.usace.hec.cwms.rating.io.xml.RatingContainerXmlFactory; import mil.army.usace.hec.cwms.rating.io.xml.RatingSetContainerXmlFactory; import mil.army.usace.hec.cwms.rating.io.xml.RatingSpecXmlFactory; @@ -61,32 +101,6 @@ import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.ValueSource; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.sql.SQLException; -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.NavigableMap; -import java.util.TreeMap; - -import hec.data.RatingException; -import hec.data.cwmsRating.io.RatingSetContainer; -import hec.data.cwmsRating.io.RatingSpecContainer; - -import static cwms.cda.api.Controllers.*; -import static cwms.cda.security.ApiKeyIdentityProvider.AUTH_HEADER; -import static helpers.FloatCloseTo.floatCloseTo; -import static io.restassured.RestAssured.given; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - @Tag("integration") public class LevelsControllerTestIT extends DataApiTestIT { @@ -2081,6 +2095,42 @@ void testStoreConstantLevel() throws Exception { .body("constant-value", equalTo(8675.309f)); } + @Test + void testStoreTimeRestrictedLevel() throws Exception { + String locName = "restrictedLoc123"; + createLocation(locName, true, OFFICE); + String levelId = String.format("%s.Elev.Ave.1Day.Regulating", locName); + ZonedDateTime time = ZonedDateTime.ofInstant(Instant.parse("2024-01-01T00:00:12Z"), ZoneId.of("UTC")); + ConstantLocationLevel level = new ConstantLocationLevel.Builder(levelId, time.toInstant()) + .withOfficeId(OFFICE) + .withLevelUnitsId("ft") + .withConstantValue(8675.309) + .withExpirationDate(time.plusYears(50).toInstant()) + .build(); + + String levelJson = Formats.format(new ContentType(Formats.JSONV2), level); + + given() + .log().ifValidationFails(LogDetail.ALL, true) + .queryParam(Controllers.OFFICE, OFFICE) + .header("Authorization", TestAccounts.KeyUser.SPK_NORMAL.toHeaderValue()) + .body(levelJson) + .contentType(Formats.JSONV2) + .when() + .redirects() + .follow(true) + .redirects() + .max(3) + .post("/levels/") + .then() + .log().ifValidationFails(LogDetail.ALL, true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_BAD_REQUEST)) + .body("details.message", equalTo("Level effective date cannot have seconds")) + .body("source", equalTo("User Input")) + .body(MESSAGE, equalTo("Bad Request")); + } + enum GetAllTestLegacy { JSON(Formats.JSON_LEGACY, Formats.JSON), XML(Formats.XML_LEGACY, Formats.XML), @@ -2414,6 +2464,42 @@ void test_get_aliases() throws Exception { ; } + @Test + void test_create_subminute_level() throws Exception { + String locName = "subminuteloc"; + createLocation(locName, true, OFFICE); + String levelId = String.format("%s.Elev.Ave.1Day.Top of Inlet", locName); + ZonedDateTime time = ZonedDateTime.ofInstant(Instant.parse("2024-01-01T00:00:25Z"), ZoneId.of("UTC")); + ConstantLocationLevel level = new ConstantLocationLevel.Builder(levelId, time.toInstant()) + .withOfficeId(OFFICE) + .withLevelUnitsId("ft") + .withConstantValue(8675.309) + .withExpirationDate(time.toInstant()) + .build(); + + String levelJson = Formats.format(new ContentType(Formats.JSONV2), level); + + given() + .log().ifValidationFails(LogDetail.ALL, true) + .queryParam(Controllers.OFFICE, OFFICE) + .header("Authorization", TestAccounts.KeyUser.SPK_NORMAL.toHeaderValue()) + .body(levelJson) + .contentType(Formats.JSONV2) + .when() + .redirects() + .follow(true) + .redirects() + .max(3) + .post("/levels/") + .then() + .log().ifValidationFails(LogDetail.ALL, true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_BAD_REQUEST)) + .body("details.message", is("Level effective date cannot have seconds")) + .body("message", is("Bad Request")) + .body("source", is("User Input")); + } + enum GetAllTestNewAliases { DEFAULT(Formats.DEFAULT, Formats.JSONV2), JSON(Formats.JSON, Formats.JSONV2), diff --git a/cwms-data-api/src/test/java/cwms/cda/api/LockControllerIT.java b/cwms-data-api/src/test/java/cwms/cda/api/LockControllerIT.java index cf0204d03..1303f1235 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/LockControllerIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/LockControllerIT.java @@ -35,6 +35,7 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; +import com.google.common.flogger.FluentLogger; import cwms.cda.api.enums.Nation; import cwms.cda.api.errors.NotFoundException; import cwms.cda.data.dao.DeleteRule; @@ -45,10 +46,10 @@ import cwms.cda.data.dao.location.kind.LockDao; import cwms.cda.data.dto.CwmsId; import cwms.cda.data.dto.Location; -import cwms.cda.data.dto.locationlevel.ConstantLocationLevel; -import cwms.cda.data.dto.locationlevel.LocationLevel; import cwms.cda.data.dto.location.kind.Lock; import cwms.cda.data.dto.location.kind.LockLocationLevelRef; +import cwms.cda.data.dto.locationlevel.ConstantLocationLevel; +import cwms.cda.data.dto.locationlevel.LocationLevel; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import fixtures.CwmsDataApiSetupCallback; @@ -65,7 +66,6 @@ import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.List; -import com.google.common.flogger.FluentLogger; import javax.servlet.http.HttpServletResponse; import mil.army.usace.hec.test.database.CwmsDatabaseContainer; import org.apache.commons.io.IOUtils; @@ -1049,28 +1049,28 @@ private static PROJECT_OBJ_T buildProject(Location projectLocation) { private List createLocationLevelList(Lock lock) { List retVal = new ArrayList<>(); - var lowLowerLevel = new ConstantLocationLevel.Builder(lock.getLowWaterLowerPoolLocationLevel().getLevelId(), ZonedDateTime.now().toInstant()) + var lowLowerLevel = new ConstantLocationLevel.Builder(lock.getLowWaterLowerPoolLocationLevel().getLevelId(), LocationLevel.truncateDate(ZonedDateTime.now()).toInstant()) .withLevelUnitsId(lock.getElevationUnits()) .withOfficeId(lock.getLowWaterLowerPoolLocationLevel().getOfficeId()) .withSpecifiedLevelId(lock.getLowWaterLowerPoolLocationLevel().getSpecifiedLevelId()) .withConstantValue(lock.getLowWaterLowerPoolLocationLevel().getLevelValue()) .build(); retVal.add(lowLowerLevel); - var lowUpperLevel = new ConstantLocationLevel.Builder(lock.getLowWaterUpperPoolLocationLevel().getLevelId(), ZonedDateTime.now().toInstant()) + var lowUpperLevel = new ConstantLocationLevel.Builder(lock.getLowWaterUpperPoolLocationLevel().getLevelId(), LocationLevel.truncateDate(ZonedDateTime.now()).toInstant()) .withLevelUnitsId(lock.getElevationUnits()) .withOfficeId(lock.getLowWaterUpperPoolLocationLevel().getOfficeId()) .withSpecifiedLevelId(lock.getLowWaterUpperPoolLocationLevel().getSpecifiedLevelId()) .withConstantValue(lock.getLowWaterUpperPoolLocationLevel().getLevelValue()) .build(); retVal.add(lowUpperLevel); - var highLowerLevel = new ConstantLocationLevel.Builder(lock.getHighWaterLowerPoolLocationLevel().getLevelId(), ZonedDateTime.now().toInstant()) + var highLowerLevel = new ConstantLocationLevel.Builder(lock.getHighWaterLowerPoolLocationLevel().getLevelId(), LocationLevel.truncateDate(ZonedDateTime.now()).toInstant()) .withLevelUnitsId(lock.getElevationUnits()) .withOfficeId(lock.getHighWaterLowerPoolLocationLevel().getOfficeId()) .withSpecifiedLevelId(lock.getHighWaterLowerPoolLocationLevel().getSpecifiedLevelId()) .withConstantValue(lock.getHighWaterLowerPoolLocationLevel().getLevelValue()) .build(); retVal.add(highLowerLevel); - var highUpperLevel = new ConstantLocationLevel.Builder(lock.getHighWaterUpperPoolLocationLevel().getLevelId(), ZonedDateTime.now().toInstant()) + var highUpperLevel = new ConstantLocationLevel.Builder(lock.getHighWaterUpperPoolLocationLevel().getLevelId(), LocationLevel.truncateDate(ZonedDateTime.now()).toInstant()) .withLevelUnitsId(lock.getElevationUnits()) .withOfficeId(lock.getHighWaterUpperPoolLocationLevel().getOfficeId()) @@ -1078,7 +1078,7 @@ private List createLocationLevelList(Lock lock) { .withConstantValue(lock.getHighWaterUpperPoolLocationLevel().getLevelValue()) .build(); retVal.add(highUpperLevel); - var warningBuffer = new ConstantLocationLevel.Builder(String.format("%s.Elev-Closure.Inst.0.Warning Buffer", lock.getLocation().getName()), ZonedDateTime.now().toInstant()) + var warningBuffer = new ConstantLocationLevel.Builder(String.format("%s.Elev-Closure.Inst.0.Warning Buffer", lock.getLocation().getName()), LocationLevel.truncateDate(ZonedDateTime.now()).toInstant()) .withLevelUnitsId(lock.getElevationUnits()) .withOfficeId(lock.getLocation().getOfficeId()) .withSpecifiedLevelId("Warning Buffer") diff --git a/cwms-data-api/src/test/java/cwms/cda/data/dao/location/kind/LockDaoIT.java b/cwms-data-api/src/test/java/cwms/cda/data/dao/location/kind/LockDaoIT.java index 485771c9c..4d0f11fab 100644 --- a/cwms-data-api/src/test/java/cwms/cda/data/dao/location/kind/LockDaoIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/data/dao/location/kind/LockDaoIT.java @@ -330,35 +330,35 @@ private Lock storeLocLevelsAndBuildStorableLock(Lock lock) throws SQLException { private List createLocationLevelList(Lock lock) { List retVal = new ArrayList<>(); - var lowLowerLevel = new ConstantLocationLevel.Builder(lock.getLowWaterLowerPoolLocationLevel().getLevelId(), ZonedDateTime.now().toInstant()) + var lowLowerLevel = new ConstantLocationLevel.Builder(lock.getLowWaterLowerPoolLocationLevel().getLevelId(), LocationLevel.truncateDate(ZonedDateTime.now()).toInstant()) .withLevelUnitsId(lock.getElevationUnits()) .withOfficeId(lock.getLowWaterLowerPoolLocationLevel().getOfficeId()) .withSpecifiedLevelId(lock.getLowWaterLowerPoolLocationLevel().getSpecifiedLevelId()) .withConstantValue(lock.getLowWaterLowerPoolLocationLevel().getLevelValue()) .build(); retVal.add(lowLowerLevel); - var lowUpperLevel = new ConstantLocationLevel.Builder(lock.getLowWaterUpperPoolLocationLevel().getLevelId(), ZonedDateTime.now().toInstant()) + var lowUpperLevel = new ConstantLocationLevel.Builder(lock.getLowWaterUpperPoolLocationLevel().getLevelId(), LocationLevel.truncateDate(ZonedDateTime.now()).toInstant()) .withLevelUnitsId(lock.getElevationUnits()) .withOfficeId(lock.getLowWaterUpperPoolLocationLevel().getOfficeId()) .withSpecifiedLevelId(lock.getLowWaterUpperPoolLocationLevel().getSpecifiedLevelId()) .withConstantValue(lock.getLowWaterUpperPoolLocationLevel().getLevelValue()) .build(); retVal.add(lowUpperLevel); - var highLowerLevel = new ConstantLocationLevel.Builder(lock.getHighWaterLowerPoolLocationLevel().getLevelId(), ZonedDateTime.now().toInstant()) + var highLowerLevel = new ConstantLocationLevel.Builder(lock.getHighWaterLowerPoolLocationLevel().getLevelId(), LocationLevel.truncateDate(ZonedDateTime.now()).toInstant()) .withLevelUnitsId(lock.getElevationUnits()) .withOfficeId(lock.getHighWaterLowerPoolLocationLevel().getOfficeId()) .withSpecifiedLevelId(lock.getHighWaterLowerPoolLocationLevel().getSpecifiedLevelId()) .withConstantValue(lock.getHighWaterLowerPoolLocationLevel().getLevelValue()) .build(); retVal.add(highLowerLevel); - var highUpperLevel = new ConstantLocationLevel.Builder(lock.getHighWaterUpperPoolLocationLevel().getLevelId(), ZonedDateTime.now().toInstant()) + var highUpperLevel = new ConstantLocationLevel.Builder(lock.getHighWaterUpperPoolLocationLevel().getLevelId(), LocationLevel.truncateDate(ZonedDateTime.now()).toInstant()) .withLevelUnitsId(lock.getElevationUnits()) .withOfficeId(lock.getHighWaterUpperPoolLocationLevel().getOfficeId()) .withSpecifiedLevelId(lock.getHighWaterUpperPoolLocationLevel().getSpecifiedLevelId()) .withConstantValue(lock.getHighWaterUpperPoolLocationLevel().getLevelValue()) .build(); retVal.add(highUpperLevel); - var warningBuffer = new ConstantLocationLevel.Builder(String.format("%s.Elev-Closure.Inst.0.Warning Buffer", lock.getLocation().getName()), ZonedDateTime.now().toInstant()) + var warningBuffer = new ConstantLocationLevel.Builder(String.format("%s.Elev-Closure.Inst.0.Warning Buffer", lock.getLocation().getName()), LocationLevel.truncateDate(ZonedDateTime.now()).toInstant()) .withLevelUnitsId(lock.getElevationUnits()) .withOfficeId(lock.getLocation().getOfficeId()) .withSpecifiedLevelId("Warning Buffer")