Handle tachograph activity times without offsets
This commit is contained in:
parent
a20d4c241e
commit
7209a73d30
|
|
@ -26,6 +26,7 @@ import java.util.UUID;
|
|||
import org.springframework.stereotype.Component;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
@Component
|
||||
|
|
@ -33,7 +34,6 @@ public class DriverCardXmlExtractionService {
|
|||
|
||||
private final DriverKeyFactory driverKeyFactory;
|
||||
private final VehicleKeyFactory vehicleKeyFactory;
|
||||
private final XmlExpressionEvaluator xml = new XmlExpressionEvaluator();
|
||||
|
||||
public DriverCardXmlExtractionService(DriverKeyFactory driverKeyFactory, VehicleKeyFactory vehicleKeyFactory) {
|
||||
this.driverKeyFactory = driverKeyFactory;
|
||||
|
|
@ -104,27 +104,28 @@ public class DriverCardXmlExtractionService {
|
|||
}
|
||||
|
||||
private ExtractedDriverCard extractDriverCard(Document document, List<ExtractionWarning> warnings) {
|
||||
Element identification = firstElement(document, "/DriverCard/Identification[1]");
|
||||
Element identification = child(document.getDocumentElement(), "Identification");
|
||||
if (identification == null) {
|
||||
warnings.add(new ExtractionWarning("MISSING_IDENTIFICATION", "Driver card identification block is missing.", "/DriverCard"));
|
||||
return null;
|
||||
}
|
||||
String cardNation = text(identification, "cardIdentification/cardIssuingMemberState");
|
||||
Element cardIdentification = child(identification, "cardIdentification");
|
||||
String cardNation = childText(cardIdentification, "cardIssuingMemberState");
|
||||
String cardNumber = joinCardNumber(identification);
|
||||
String authority = text(identification, "cardIdentification/cardIssuingAuthorityName/name");
|
||||
String authority = childText(child(cardIdentification, "cardIssuingAuthorityName"), "name");
|
||||
return new ExtractedDriverCard(
|
||||
null,
|
||||
cardNation,
|
||||
cardNumber,
|
||||
authority,
|
||||
offsetDateTime(text(identification, "cardIdentification/cardIssueDate")),
|
||||
offsetDateTime(text(identification, "cardIdentification/cardValidityBegin")),
|
||||
offsetDateTime(text(identification, "cardIdentification/cardExpiryDate"))
|
||||
offsetDateTime(childText(cardIdentification, "cardIssueDate")),
|
||||
offsetDateTime(childText(cardIdentification, "cardValidityBegin")),
|
||||
offsetDateTime(childText(cardIdentification, "cardExpiryDate"))
|
||||
);
|
||||
}
|
||||
|
||||
private ExtractedDriver extractDriver(Document document, String driverKey, List<ExtractionWarning> warnings) {
|
||||
Element identification = firstElement(document, "/DriverCard/Identification[1]");
|
||||
Element identification = child(document.getDocumentElement(), "Identification");
|
||||
if (identification == null) {
|
||||
warnings.add(new ExtractionWarning("MISSING_DRIVER", "Driver holder identification block is missing.", "/DriverCard"));
|
||||
return new ExtractedDriver(
|
||||
|
|
@ -139,17 +140,20 @@ public class DriverCardXmlExtractionService {
|
|||
null
|
||||
);
|
||||
}
|
||||
Element licenceInfo = firstElement(document, "/DriverCard/DrivingLicenseInfo[1]");
|
||||
Element driverCardHolderIdentification = child(identification, "driverCardHolderIdentification");
|
||||
Element cardHolderName = child(driverCardHolderIdentification, "cardHolderName");
|
||||
Element licenceInfo = child(document.getDocumentElement(), "DrivingLicenseInfo");
|
||||
Element cardDrivingLicenseInformation = child(licenceInfo, "cardDrivingLicenseInformation");
|
||||
return new ExtractedDriver(
|
||||
driverKey,
|
||||
driverKeyFactory.createSourceDriverId(driverKey),
|
||||
text(identification, "driverCardHolderIdentification/cardHolderName/holderSurname/name"),
|
||||
text(identification, "driverCardHolderIdentification/cardHolderName/holderFirstNames/name"),
|
||||
localDate(identification, "driverCardHolderIdentification/cardHolderBirthDate"),
|
||||
text(identification, "driverCardHolderIdentification/cardHolderPreferredLanguage"),
|
||||
text(licenceInfo, "cardDrivingLicenseInformation/drivingLicenceNumber"),
|
||||
text(licenceInfo, "cardDrivingLicenseInformation/drivingLicenceIssuingNation"),
|
||||
text(licenceInfo, "cardDrivingLicenseInformation/drivingLicenceIssuingAuthority/name")
|
||||
childText(child(cardHolderName, "holderSurname"), "name"),
|
||||
childText(child(cardHolderName, "holderFirstNames"), "name"),
|
||||
localDate(child(driverCardHolderIdentification, "cardHolderBirthDate")),
|
||||
childText(driverCardHolderIdentification, "cardHolderPreferredLanguage"),
|
||||
childText(cardDrivingLicenseInformation, "drivingLicenceNumber"),
|
||||
childText(cardDrivingLicenseInformation, "drivingLicenceIssuingNation"),
|
||||
childText(child(cardDrivingLicenseInformation, "drivingLicenceIssuingAuthority"), "name")
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -159,15 +163,17 @@ public class DriverCardXmlExtractionService {
|
|||
Map<String, ExtractedVehicle> vehiclesByKey,
|
||||
List<ExtractionWarning> warnings
|
||||
) {
|
||||
NodeList records = nodes(document, "/DriverCard/VehiclesUsed/cardVehiclesUsed/cardVehicleRecords");
|
||||
List<ExtractedCardVehicleUsageInterval> intervals = new ArrayList<>();
|
||||
for (int i = 0; i < records.getLength(); i++) {
|
||||
Element record = (Element) records.item(i);
|
||||
Element cardVehiclesUsed = child(child(document.getDocumentElement(), "VehiclesUsed"), "cardVehiclesUsed");
|
||||
List<Element> records = children(cardVehiclesUsed, "cardVehicleRecords");
|
||||
List<ExtractedCardVehicleUsageInterval> intervals = new ArrayList<>(records.size());
|
||||
for (int i = 0; i < records.size(); i++) {
|
||||
Element record = records.get(i);
|
||||
String path = "/DriverCard/VehiclesUsed/cardVehiclesUsed/cardVehicleRecords[" + (i + 1) + "]";
|
||||
OffsetDateTime from = offsetDateTime(text(record, "vehicleFirstUse"));
|
||||
OffsetDateTime to = offsetDateTime(text(record, "vehicleLastUse"));
|
||||
String registrationNation = text(record, "vehicleRegistration/vehicleRegistrationNation");
|
||||
String registrationNumber = text(record, "vehicleRegistration/vehicleRegistrationNumber/vehicleRegNumber");
|
||||
OffsetDateTime from = offsetDateTime(childText(record, "vehicleFirstUse"));
|
||||
OffsetDateTime to = offsetDateTime(childText(record, "vehicleLastUse"));
|
||||
Element vehicleRegistration = child(record, "vehicleRegistration");
|
||||
String registrationNation = childText(vehicleRegistration, "vehicleRegistrationNation");
|
||||
String registrationNumber = childText(child(vehicleRegistration, "vehicleRegistrationNumber"), "vehicleRegNumber");
|
||||
String registrationKey = vehicleKeyFactory.createRegistrationKey(registrationNation, registrationNumber);
|
||||
registrationsByKey.putIfAbsent(
|
||||
registrationKey,
|
||||
|
|
@ -178,7 +184,7 @@ public class DriverCardXmlExtractionService {
|
|||
registrationNumber
|
||||
)
|
||||
);
|
||||
String vin = text(record, "vehicleIdentificationNumber");
|
||||
String vin = childText(record, "vehicleIdentificationNumber");
|
||||
String vehicleKey = vehicleKeyFactory.createVehicleKey(vin);
|
||||
if (vehicleKey != null) {
|
||||
vehiclesByKey.putIfAbsent(
|
||||
|
|
@ -194,8 +200,8 @@ public class DriverCardXmlExtractionService {
|
|||
"CVU-" + (i + 1),
|
||||
from,
|
||||
to,
|
||||
longValue(text(record, "vehicleOdometerBegin")),
|
||||
longValue(text(record, "vehicleOdometerEnd")),
|
||||
longValue(childText(record, "vehicleOdometerBegin")),
|
||||
longValue(childText(record, "vehicleOdometerEnd")),
|
||||
registrationKey,
|
||||
vehicleKey,
|
||||
path
|
||||
|
|
@ -206,33 +212,34 @@ public class DriverCardXmlExtractionService {
|
|||
}
|
||||
|
||||
private List<ExtractedCardActivityInterval> extractActivityIntervals(Document document, List<ExtractionWarning> warnings) {
|
||||
NodeList dayRecords = nodes(document, "/DriverCard/DriverActivityData/cardDriverActivity/cardActivityDailyRecord");
|
||||
List<ExtractedCardActivityInterval> intervals = new ArrayList<>();
|
||||
Element cardDriverActivity = child(child(document.getDocumentElement(), "DriverActivityData"), "cardDriverActivity");
|
||||
List<Element> dayRecords = children(cardDriverActivity, "cardActivityDailyRecord");
|
||||
List<ExtractedCardActivityInterval> intervals = new ArrayList<>(dayRecords.size() * 8);
|
||||
int intervalNo = 0;
|
||||
for (int dayIndex = 0; dayIndex < dayRecords.getLength(); dayIndex++) {
|
||||
Element dayRecord = (Element) dayRecords.item(dayIndex);
|
||||
for (int dayIndex = 0; dayIndex < dayRecords.size(); dayIndex++) {
|
||||
Element dayRecord = dayRecords.get(dayIndex);
|
||||
String dayPath = "/DriverCard/DriverActivityData/cardDriverActivity/cardActivityDailyRecord[" + (dayIndex + 1) + "]";
|
||||
OffsetDateTime recordDate = offsetDateTime(text(dayRecord, "activityRecordDate"));
|
||||
OffsetDateTime recordDate = offsetDateTime(childText(dayRecord, "activityRecordDate"));
|
||||
if (recordDate == null) {
|
||||
warnings.add(new ExtractionWarning("MISSING_ACTIVITY_RECORD_DATE", "Activity daily record has no activityRecordDate.", dayPath));
|
||||
continue;
|
||||
}
|
||||
LocalDate date = recordDate.withOffsetSameInstant(ZoneOffset.UTC).toLocalDate();
|
||||
NodeList changes = nodes(dayRecord, "activityChangeInfos");
|
||||
List<ActivityChange> parsedChanges = new ArrayList<>();
|
||||
for (int changeIndex = 0; changeIndex < changes.getLength(); changeIndex++) {
|
||||
Element change = (Element) changes.item(changeIndex);
|
||||
OffsetDateTime from = combine(date, text(change, "timeOfChange"));
|
||||
List<Element> changes = children(dayRecord, "activityChangeInfos");
|
||||
List<ActivityChange> parsedChanges = new ArrayList<>(changes.size());
|
||||
for (int changeIndex = 0; changeIndex < changes.size(); changeIndex++) {
|
||||
Element change = changes.get(changeIndex);
|
||||
OffsetDateTime from = combine(date, childText(change, "timeOfChange"));
|
||||
if (from == null) {
|
||||
warnings.add(new ExtractionWarning("INVALID_ACTIVITY_CHANGE_TIME", "Activity change has invalid timeOfChange.", dayPath + "/activityChangeInfos[" + (changeIndex + 1) + "]"));
|
||||
continue;
|
||||
}
|
||||
parsedChanges.add(new ActivityChange(
|
||||
from,
|
||||
normalizeActivity(text(change, "activity")),
|
||||
normalizeToken(text(change, "slot")),
|
||||
normalizeToken(text(change, "cardStatus")),
|
||||
normalizeToken(text(change, "drivingStatus")),
|
||||
normalizeActivity(childText(change, "activity")),
|
||||
normalizeToken(childText(change, "slot")),
|
||||
normalizeToken(childText(change, "cardStatus")),
|
||||
normalizeToken(childText(change, "drivingStatus")),
|
||||
dayPath + "/activityChangeInfos[" + (changeIndex + 1) + "]"
|
||||
));
|
||||
}
|
||||
|
|
@ -351,20 +358,42 @@ public class DriverCardXmlExtractionService {
|
|||
return timestamp.plusSeconds(1);
|
||||
}
|
||||
|
||||
private Element firstElement(Object node, String expression) {
|
||||
NodeList nodes = nodes(node, expression);
|
||||
if (nodes.getLength() == 0) {
|
||||
private Element child(Element parent, String name) {
|
||||
if (parent == null) {
|
||||
return null;
|
||||
}
|
||||
return (Element) nodes.item(0);
|
||||
NodeList childNodes = parent.getChildNodes();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
Node child = childNodes.item(i);
|
||||
if (child.getNodeType() == Node.ELEMENT_NODE && name.equals(child.getNodeName())) {
|
||||
return (Element) child;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private NodeList nodes(Object node, String expression) {
|
||||
return xml.nodes(node, expression);
|
||||
private List<Element> children(Element parent, String name) {
|
||||
if (parent == null) {
|
||||
return List.of();
|
||||
}
|
||||
NodeList childNodes = parent.getChildNodes();
|
||||
List<Element> children = new ArrayList<>();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
Node child = childNodes.item(i);
|
||||
if (child.getNodeType() == Node.ELEMENT_NODE && name.equals(child.getNodeName())) {
|
||||
children.add((Element) child);
|
||||
}
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
private String text(Object node, String expression) {
|
||||
return xml.text(node, expression);
|
||||
private String childText(Element parent, String name) {
|
||||
Element child = child(parent, name);
|
||||
if (child == null) {
|
||||
return null;
|
||||
}
|
||||
String value = child.getTextContent();
|
||||
return value == null || value.isBlank() ? null : value.trim();
|
||||
}
|
||||
|
||||
private OffsetDateTime offsetDateTime(String value) {
|
||||
|
|
@ -374,14 +403,13 @@ public class DriverCardXmlExtractionService {
|
|||
return OffsetDateTime.parse(value.trim()).withOffsetSameInstant(ZoneOffset.UTC);
|
||||
}
|
||||
|
||||
private LocalDate localDate(Element element, String expression) {
|
||||
Element dateElement = firstElement(element, expression);
|
||||
private LocalDate localDate(Element dateElement) {
|
||||
if (dateElement == null) {
|
||||
return null;
|
||||
}
|
||||
String year = text(dateElement, "year");
|
||||
String month = text(dateElement, "month");
|
||||
String day = text(dateElement, "day");
|
||||
String year = childText(dateElement, "year");
|
||||
String month = childText(dateElement, "month");
|
||||
String day = childText(dateElement, "day");
|
||||
if (year == null || month == null || day == null) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -389,11 +417,7 @@ public class DriverCardXmlExtractionService {
|
|||
}
|
||||
|
||||
private OffsetDateTime combine(LocalDate date, String timeText) {
|
||||
if (date == null || timeText == null || timeText.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
LocalTime time = java.time.OffsetTime.parse(timeText.trim()).withOffsetSameInstant(ZoneOffset.UTC).toLocalTime();
|
||||
return date.atTime(time).atOffset(ZoneOffset.UTC);
|
||||
return TachographTimeParser.combineUtc(date, timeText);
|
||||
}
|
||||
|
||||
private Long longValue(String value) {
|
||||
|
|
@ -435,12 +459,14 @@ public class DriverCardXmlExtractionService {
|
|||
}
|
||||
|
||||
private String joinCardNumber(Element identification) {
|
||||
String driverIdentification = text(identification, "cardIdentification/cardNumber/driverIdentification");
|
||||
Element cardIdentification = child(identification, "cardIdentification");
|
||||
Element cardNumber = child(cardIdentification, "cardNumber");
|
||||
String driverIdentification = childText(cardNumber, "driverIdentification");
|
||||
if (driverIdentification == null) {
|
||||
return null;
|
||||
}
|
||||
String replacement = text(identification, "cardIdentification/cardNumber/cardReplacementIndex");
|
||||
String renewal = text(identification, "cardIdentification/cardNumber/cardRenewalIndex");
|
||||
String replacement = childText(cardNumber, "cardReplacementIndex");
|
||||
String renewal = childText(cardNumber, "cardRenewalIndex");
|
||||
StringBuilder builder = new StringBuilder(driverIdentification);
|
||||
if (replacement != null) {
|
||||
builder.append(replacement);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
package at.procon.eventhub.tachographfilesession.service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeParseException;
|
||||
|
||||
final class TachographTimeParser {
|
||||
|
||||
private TachographTimeParser() {
|
||||
}
|
||||
|
||||
static OffsetDateTime combineUtc(LocalDate date, String timeText) {
|
||||
if (date == null || timeText == null || timeText.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String normalized = timeText.trim();
|
||||
try {
|
||||
OffsetTime offsetTime = OffsetTime.parse(normalized);
|
||||
return date.atTime(offsetTime.toLocalTime())
|
||||
.atOffset(offsetTime.getOffset())
|
||||
.withOffsetSameInstant(ZoneOffset.UTC);
|
||||
} catch (DateTimeParseException ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
return date.atTime(LocalTime.parse(normalized)).atOffset(ZoneOffset.UTC);
|
||||
} catch (DateTimeParseException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -727,11 +727,7 @@ public class VehicleUnitXmlExtractionService {
|
|||
}
|
||||
|
||||
private OffsetDateTime combine(LocalDate date, String timeText) {
|
||||
if (date == null || timeText == null || timeText.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
LocalTime time = java.time.OffsetTime.parse(timeText.trim()).withOffsetSameInstant(ZoneOffset.UTC).toLocalTime();
|
||||
return date.atTime(time).atOffset(ZoneOffset.UTC);
|
||||
return TachographTimeParser.combineUtc(date, timeText);
|
||||
}
|
||||
|
||||
private String normalizeActivity(String value) {
|
||||
|
|
|
|||
|
|
@ -52,4 +52,31 @@ class DriverCardXmlExtractionServiceTest {
|
|||
assertThat(driver.cardActivityIntervals().get(3).registrationKey()).isEqualTo("12:W-54321B");
|
||||
assertThat(driver.cardActivityIntervals().get(4).registrationKey()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void extractsActivitiesWhenTimeOfChangeHasNoOffset() {
|
||||
TachographFileSession session = service.extract(
|
||||
parser.parse(DriverCardXmlSamples.validDriverCardXmlWithLocalActivityTimes()),
|
||||
new TachographFileSessionMetadata(
|
||||
"default",
|
||||
"legalrequirements-drivercard",
|
||||
"sample",
|
||||
"sample.ddd",
|
||||
"abc",
|
||||
10,
|
||||
"42",
|
||||
"def",
|
||||
true,
|
||||
null
|
||||
),
|
||||
Instant.now(),
|
||||
Instant.now().plus(4, ChronoUnit.HOURS)
|
||||
);
|
||||
|
||||
DriverExtractionSession driver = session.driversByKey().values().iterator().next();
|
||||
assertThat(driver.cardActivityIntervals()).hasSize(5);
|
||||
assertThat(driver.cardActivityIntervals())
|
||||
.extracting(interval -> interval.from().toString())
|
||||
.contains("2026-04-01T08:00Z", "2026-04-01T12:30Z");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,4 +112,11 @@ final class DriverCardXmlSamples {
|
|||
</DriverCard>
|
||||
""";
|
||||
}
|
||||
|
||||
static String validDriverCardXmlWithLocalActivityTimes() {
|
||||
return validDriverCardXml()
|
||||
.replace("<timeOfChange>08:00:00Z</timeOfChange>", "<timeOfChange>08:00:00</timeOfChange>")
|
||||
.replace("<timeOfChange>09:00:00Z</timeOfChange>", "<timeOfChange>09:00:00</timeOfChange>")
|
||||
.replace("<timeOfChange>12:30:00Z</timeOfChange>", "<timeOfChange>12:30:00</timeOfChange>");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
package at.procon.eventhub.tachographfilesession.service;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class TachographTimeParserTest {
|
||||
|
||||
@Test
|
||||
void combinesPlainLocalTimeAsUtc() {
|
||||
assertThat(TachographTimeParser.combineUtc(LocalDate.of(2026, 4, 1), "00:00:00"))
|
||||
.hasToString("2026-04-01T00:00Z");
|
||||
}
|
||||
|
||||
@Test
|
||||
void preservesDateShiftWhenOffsetTimeCrossesUtcMidnight() {
|
||||
assertThat(TachographTimeParser.combineUtc(LocalDate.of(2026, 4, 1), "00:30:00+02:00"))
|
||||
.hasToString("2026-03-31T22:30Z");
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnsNullForInvalidTimeText() {
|
||||
assertThat(TachographTimeParser.combineUtc(LocalDate.of(2026, 4, 1), "not-a-time")).isNull();
|
||||
}
|
||||
}
|
||||
|
|
@ -76,6 +76,32 @@ class VehicleUnitXmlExtractionServiceTest {
|
|||
.contains("OPEN_VU_CARD_INTERVAL", "VU_ACTIVITY_UNASSIGNED");
|
||||
}
|
||||
|
||||
@Test
|
||||
void extractsActivitiesWhenVuTimeOfChangeHasNoOffset() throws Exception {
|
||||
TachographFileSession session = service.extract(
|
||||
new TachographXmlParser.ParsedTachographXml(document(VehicleUnitXmlSamples.vehicleUnitXmlWithLocalActivityTimes()), "VehicleUnit"),
|
||||
new TachographFileSessionMetadata(
|
||||
"default",
|
||||
"legalrequirements-vehicleunit",
|
||||
"sample-vu",
|
||||
"sample-vu.ddd",
|
||||
"abc",
|
||||
10,
|
||||
"42",
|
||||
"def",
|
||||
false,
|
||||
null
|
||||
),
|
||||
Instant.now(),
|
||||
Instant.now().plus(4, ChronoUnit.HOURS)
|
||||
);
|
||||
|
||||
DriverExtractionSession firstDriver = session.driversByKey().get("12:12345678901200");
|
||||
DriverExtractionSession secondDriver = session.driversByKey().get("12:99999999999911");
|
||||
assertThat(firstDriver.cardActivityIntervals().get(0).from().toString()).isEqualTo("2026-04-01T08:00Z");
|
||||
assertThat(secondDriver.cardActivityIntervals().get(0).from().toString()).isEqualTo("2026-04-02T07:30Z");
|
||||
}
|
||||
|
||||
private Document document(String xml) throws Exception {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(false);
|
||||
|
|
|
|||
|
|
@ -173,4 +173,12 @@ final class VehicleUnitXmlSamples {
|
|||
</VehicleUnit>
|
||||
""";
|
||||
}
|
||||
|
||||
static String vehicleUnitXmlWithLocalActivityTimes() {
|
||||
return vehicleUnitXml()
|
||||
.replace("<timeOfChange>08:00:00Z</timeOfChange>", "<timeOfChange>08:00:00</timeOfChange>")
|
||||
.replace("<timeOfChange>09:00:00Z</timeOfChange>", "<timeOfChange>09:00:00</timeOfChange>")
|
||||
.replace("<timeOfChange>11:00:00Z</timeOfChange>", "<timeOfChange>11:00:00</timeOfChange>")
|
||||
.replace("<timeOfChange>07:30:00Z</timeOfChange>", "<timeOfChange>07:30:00</timeOfChange>");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue