diff --git a/src/main/java/org/spacious_team/table_wrapper/api/DateTimeFormatParser.java b/src/main/java/org/spacious_team/table_wrapper/api/DateTimeFormatParser.java new file mode 100644 index 0000000..aef0c86 --- /dev/null +++ b/src/main/java/org/spacious_team/table_wrapper/api/DateTimeFormatParser.java @@ -0,0 +1,221 @@ +/* + * Table Wrapper API + * Copyright (C) 2022 Spacious Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.spacious_team.table_wrapper.api; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.time.format.DateTimeFormatter; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import static lombok.AccessLevel.PRIVATE; + +@NoArgsConstructor(access = PRIVATE) +final class DateTimeFormatParser { + + private static final Map dateTimeFormatters = new ConcurrentHashMap<>(); + + static DateTimeFormatter getDateTimeFormatter(String dateTimeOffset) { + Pattern pattern = getPattern(dateTimeOffset); + return getDateTimeFormatter(pattern); + } + + private static Pattern getPattern(String dateTimeOffset) { + @Nullable Pattern pattern = null; + int length = dateTimeOffset.length(); + if (length == 8 || length == 12) { // without and with millis + pattern = getForTime(dateTimeOffset, 0); + } else if (length == 10) { + pattern = getForDate(dateTimeOffset, 0); + } else if (length == 19 || length == 23) { // without and with millis + pattern = getForDateTime(dateTimeOffset); + } else if (length > 19) { + pattern = getForDateTimeZone(dateTimeOffset); + } + if (pattern == null) { + throw new IllegalArgumentException("Unknown date time format for: " + dateTimeOffset); + } + return pattern; + } + + private static TimePattern getForTime(String time, int offset) { + boolean hasMillis = (time.length() > (offset + 8)) && (time.charAt(offset + 8) == '.'); + return TimePattern.of(hasMillis); + } + + private static DatePattern getForDate(String date, int dateOffset) { + boolean isYearAtFirst; + char dateSplitter; + char ch = date.charAt(dateOffset + 2); + if (!Character.isDigit(ch)) { + // date format is DD MM YYYY + isYearAtFirst = false; + dateSplitter = ch; + } else { + // date format is YYYY MM DD + isYearAtFirst = true; + dateSplitter = date.charAt(dateOffset + 4); + } + return DatePattern.of(isYearAtFirst, dateSplitter); + } + + private static DateTimePattern getForDateTime(String dateTime) { + boolean isDateAtFirst; + DatePattern datePattern; + TimePattern timePattern; + char dateTimeSeparator; + if (dateTime.charAt(2) == ':') { + // format is