From 8fd294a75ad9990f63c09811b62d8773800b81ca Mon Sep 17 00:00:00 2001 From: Vitalii Diravka Date: Tue, 26 Apr 2022 17:09:02 +0300 Subject: [PATCH] DRILL-8195: Add Timestamp Zone offset ISO-8601 format for JSON EVF --- .../common/util/DrillDateTimeFormatter.java | 34 +++++++++++++++++++ .../values/UtcTimestampValueListener.java | 6 ++-- .../exec/vector/complex/fn/VectorOutput.java | 14 +++----- 3 files changed, 42 insertions(+), 12 deletions(-) create mode 100644 common/src/main/java/org/apache/drill/common/util/DrillDateTimeFormatter.java diff --git a/common/src/main/java/org/apache/drill/common/util/DrillDateTimeFormatter.java b/common/src/main/java/org/apache/drill/common/util/DrillDateTimeFormatter.java new file mode 100644 index 00000000000..30786fc1cde --- /dev/null +++ b/common/src/main/java/org/apache/drill/common/util/DrillDateTimeFormatter.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.drill.common.util; + +import java.time.format.DateTimeFormatterBuilder; + + +/** + * Extends regular {@link java.time.Instant#parse} with more formats. + * By default, {@link java.time.format.DateTimeFormatter#ISO_INSTANT} used. + */ +public class DrillDateTimeFormatter { + public static java.time.format.DateTimeFormatter ISO_DATETIME_FORMATTER = + new DateTimeFormatterBuilder().append(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME) + .optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd() + .optionalStart().appendOffset("+HHMM", "+0000").optionalEnd() + .optionalStart().appendOffset("+HH", "Z").optionalEnd() + .toFormatter(); +} diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/easy/json/values/UtcTimestampValueListener.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/easy/json/values/UtcTimestampValueListener.java index 662e87dbec3..3d4b917cb5c 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/easy/json/values/UtcTimestampValueListener.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/easy/json/values/UtcTimestampValueListener.java @@ -26,6 +26,8 @@ import com.fasterxml.jackson.core.JsonToken; +import static org.apache.drill.common.util.DrillDateTimeFormatter.ISO_DATETIME_FORMATTER; + /** * Per the * V1 docs: @@ -59,7 +61,7 @@ public void onValue(JsonToken token, TokenIterator tokenizer) { break; case VALUE_STRING: try { - instant = Instant.parse(tokenizer.stringValue()); + instant = ISO_DATETIME_FORMATTER.parse(tokenizer.stringValue(), Instant::from); } catch (Exception e) { throw loader.dataConversionError(schema(), "date", tokenizer.stringValue()); } @@ -67,6 +69,6 @@ public void onValue(JsonToken token, TokenIterator tokenizer) { default: throw tokenizer.invalidValue(token); } - writer.setLong(instant.toEpochMilli() + LOCAL_ZONE_ID.getRules().getOffset(instant).getTotalSeconds() * 1000); + writer.setLong(instant.toEpochMilli() + LOCAL_ZONE_ID.getRules().getOffset(instant).getTotalSeconds() * 1000L); } } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/vector/complex/fn/VectorOutput.java b/exec/java-exec/src/main/java/org/apache/drill/exec/vector/complex/fn/VectorOutput.java index 040679a2c35..2ed52fd9c1f 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/vector/complex/fn/VectorOutput.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/vector/complex/fn/VectorOutput.java @@ -25,8 +25,6 @@ import java.time.OffsetTime; import java.time.ZoneId; import java.time.ZoneOffset; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; import org.apache.drill.common.exceptions.UserException; import org.apache.drill.exec.expr.fn.impl.DateUtility; @@ -58,6 +56,8 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; +import static org.apache.drill.common.util.DrillDateTimeFormatter.ISO_DATETIME_FORMATTER; + abstract class VectorOutput { private static final Logger logger = LoggerFactory.getLogger(VectorOutput.class); @@ -74,12 +74,6 @@ abstract class VectorOutput { protected final WorkingBuffer work; protected JsonParser parser; - protected DateTimeFormatter isoDateTimeFormatter = new DateTimeFormatterBuilder().append(DateTimeFormatter.ISO_LOCAL_DATE_TIME) - .optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd() - .optionalStart().appendOffset("+HHMM", "+0000").optionalEnd() - .optionalStart().appendOffset("+HH", "Z").optionalEnd() - .toFormatter(); - public VectorOutput(WorkingBuffer work) { this.work = work; } @@ -260,7 +254,7 @@ public void writeTimestamp(boolean isNull) throws IOException { // See the mongo specs and the Drill handler (in new JSON loader) : // 1. https://docs.mongodb.com/manual/reference/mongodb-extended-json // 2. org.apache.drill.exec.store.easy.json.values.UtcTimestampValueListener - Instant instant = isoDateTimeFormatter.parse(parser.getValueAsString(), Instant::from); + Instant instant = ISO_DATETIME_FORMATTER.parse(parser.getValueAsString(), Instant::from); long offset = ZoneId.systemDefault().getRules().getOffset(instant).getTotalSeconds() * 1000L; ts.writeTimeStamp(instant.toEpochMilli() + offset); break; @@ -366,7 +360,7 @@ public void writeTimestamp(boolean isNull) throws IOException { // See the mongo specs and the Drill handler (in new JSON loader) : // 1. https://docs.mongodb.com/manual/reference/mongodb-extended-json // 2. org.apache.drill.exec.store.easy.json.values.UtcTimestampValueListener - Instant instant = isoDateTimeFormatter.parse(parser.getValueAsString(), Instant::from); + Instant instant = ISO_DATETIME_FORMATTER.parse(parser.getValueAsString(), Instant::from); long offset = ZoneId.systemDefault().getRules().getOffset(instant).getTotalSeconds() * 1000L; ts.writeTimeStamp(instant.toEpochMilli() + offset); break;