From b9e7eed1e415cb9ce3678c41b7d67d358546263c Mon Sep 17 00:00:00 2001 From: erik182182 Date: Tue, 26 Apr 2022 15:06:32 +0300 Subject: [PATCH] Added ISO8601 formats for Date Converter, converter for LocalDate - #493 resolves --- .../jcommander/converters/DateConverter.java | 59 +++++++++++++++++++ .../converters/ISO8601DateConverter.java | 17 +++--- .../converters/ISO8601LocalDateConverter.java | 43 ++++++++++++++ .../internal/DefaultConverterFactory.java | 18 ++---- .../converters/ISO8601DateConverterTest.java | 50 ++++++++++++++++ .../ISO8601LocalDateConverterTest.java | 49 +++++++++++++++ 6 files changed, 214 insertions(+), 22 deletions(-) create mode 100644 src/main/java/com/beust/jcommander/converters/DateConverter.java create mode 100644 src/main/java/com/beust/jcommander/converters/ISO8601LocalDateConverter.java create mode 100644 src/test/java/com/beust/jcommander/converters/ISO8601DateConverterTest.java create mode 100644 src/test/java/com/beust/jcommander/converters/ISO8601LocalDateConverterTest.java diff --git a/src/main/java/com/beust/jcommander/converters/DateConverter.java b/src/main/java/com/beust/jcommander/converters/DateConverter.java new file mode 100644 index 000000000..b31fd198a --- /dev/null +++ b/src/main/java/com/beust/jcommander/converters/DateConverter.java @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2010 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed 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 com.beust.jcommander.converters; + +import java.util.ArrayList; +import java.util.List; + +/** + * Converts a String to a Date. + * + * @author Ernest Kalimullin + */ +public abstract class DateConverter extends BaseConverter { + + protected static final List DATE_FORMAT_LIST = new ArrayList<>(); + + static { + initPatterns( + "yyyy-MM-dd", + "yyyy-MM", + "dd.MM.yyyy", + "MM/dd/yy", + "hh:mm", + "hhmmss", + "hh:mm:ss" + ); + } + + public DateConverter(String optionName) { + super(optionName); + } + + private static void initPatterns(String... patterns) { + for (String pattern : patterns) { + try { + DATE_FORMAT_LIST.add(pattern); + } catch (IllegalArgumentException e) { + throw new IllegalStateException("Incorrect date pattern.", e); + } + } + } + +} diff --git a/src/main/java/com/beust/jcommander/converters/ISO8601DateConverter.java b/src/main/java/com/beust/jcommander/converters/ISO8601DateConverter.java index 230361bd4..c9427b706 100644 --- a/src/main/java/com/beust/jcommander/converters/ISO8601DateConverter.java +++ b/src/main/java/com/beust/jcommander/converters/ISO8601DateConverter.java @@ -26,23 +26,24 @@ /** * Converts a String to a Date. - * TODO Modify to work with all valid ISO 8601 date formats (currently only works with yyyy-MM-dd). * * @author Angus Smithson */ -public class ISO8601DateConverter extends BaseConverter { - - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); +public class ISO8601DateConverter extends DateConverter { public ISO8601DateConverter(String optionName) { super(optionName); } public Date convert(String value) { - try { - return DATE_FORMAT.parse(value); - } catch (ParseException pe) { - throw new ParameterException(getErrorString(value, String.format("an ISO-8601 formatted date (%s)", DATE_FORMAT.toPattern()))); + for (String format : DATE_FORMAT_LIST) { + try { + return new SimpleDateFormat(format).parse(value); + } catch (ParseException ignored) { + continue; + } } + throw new ParameterException(getErrorString(value, "an ISO-8601 formatted date")); } + } diff --git a/src/main/java/com/beust/jcommander/converters/ISO8601LocalDateConverter.java b/src/main/java/com/beust/jcommander/converters/ISO8601LocalDateConverter.java new file mode 100644 index 000000000..f196ffa23 --- /dev/null +++ b/src/main/java/com/beust/jcommander/converters/ISO8601LocalDateConverter.java @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2010 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + *

+ * Licensed 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 com.beust.jcommander.converters; + +import com.beust.jcommander.ParameterException; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +public class ISO8601LocalDateConverter extends DateConverter { + + public ISO8601LocalDateConverter(String optionName) { + super(optionName); + } + + public LocalDate convert(String value) { + for (String pattern : DATE_FORMAT_LIST) { + try { + return LocalDate.parse(value, DateTimeFormatter.ofPattern(pattern)); + } catch (DateTimeParseException ignored) { + continue; + } + } + throw new ParameterException(getErrorString(value, "an ISO-8601 formatted time")); + } +} diff --git a/src/main/java/com/beust/jcommander/internal/DefaultConverterFactory.java b/src/main/java/com/beust/jcommander/internal/DefaultConverterFactory.java index be7b05be4..daeeb0cb5 100644 --- a/src/main/java/com/beust/jcommander/internal/DefaultConverterFactory.java +++ b/src/main/java/com/beust/jcommander/internal/DefaultConverterFactory.java @@ -20,26 +20,15 @@ import com.beust.jcommander.IStringConverter; import com.beust.jcommander.IStringConverterFactory; -import com.beust.jcommander.converters.BigDecimalConverter; -import com.beust.jcommander.converters.BooleanConverter; -import com.beust.jcommander.converters.DoubleConverter; -import com.beust.jcommander.converters.FileConverter; -import com.beust.jcommander.converters.FloatConverter; -import com.beust.jcommander.converters.ISO8601DateConverter; -import com.beust.jcommander.converters.IntegerConverter; -import com.beust.jcommander.converters.LongConverter; -import com.beust.jcommander.converters.StringConverter; -import com.beust.jcommander.converters.PathConverter; -import com.beust.jcommander.converters.URIConverter; -import com.beust.jcommander.converters.URLConverter; +import com.beust.jcommander.converters.*; import java.io.File; -import java.lang.NoClassDefFoundError; import java.math.BigDecimal; -import java.util.Date; import java.net.URI; import java.net.URL; import java.nio.file.Path; +import java.time.LocalDate; +import java.util.Date; import java.util.Map; public class DefaultConverterFactory implements IStringConverterFactory { @@ -64,6 +53,7 @@ public class DefaultConverterFactory implements IStringConverterFactory { classConverters.put(File.class, FileConverter.class); classConverters.put(BigDecimal.class, BigDecimalConverter.class); classConverters.put(Date.class, ISO8601DateConverter.class); + classConverters.put(LocalDate.class, ISO8601LocalDateConverter.class); classConverters.put(URI.class, URIConverter.class); classConverters.put(URL.class, URLConverter.class); diff --git a/src/test/java/com/beust/jcommander/converters/ISO8601DateConverterTest.java b/src/test/java/com/beust/jcommander/converters/ISO8601DateConverterTest.java new file mode 100644 index 000000000..c89f6ab28 --- /dev/null +++ b/src/test/java/com/beust/jcommander/converters/ISO8601DateConverterTest.java @@ -0,0 +1,50 @@ +/** + * Copyright (C) 2010 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed 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 com.beust.jcommander.converters; + +import com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameter; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +@Test +public class ISO8601DateConverterTest { + + @Test + public void testDate() throws ParseException { + class Arg { + @Parameter(names = "-date", converter = ISO8601DateConverter.class) + Date date; + } + String format = "dd.MM.yyyy"; + + SimpleDateFormat formatter = new SimpleDateFormat(format); + Date dateNow = formatter.parse(formatter.format(new Date())); + Arg command = new Arg(); + JCommander jc = JCommander.newBuilder().addObject(command).build(); + jc.parse("-date", new SimpleDateFormat(format).format(dateNow)); + + Assert.assertEquals(command.date, dateNow); + } + +} diff --git a/src/test/java/com/beust/jcommander/converters/ISO8601LocalDateConverterTest.java b/src/test/java/com/beust/jcommander/converters/ISO8601LocalDateConverterTest.java new file mode 100644 index 000000000..0ab77aff7 --- /dev/null +++ b/src/test/java/com/beust/jcommander/converters/ISO8601LocalDateConverterTest.java @@ -0,0 +1,49 @@ +/** + * Copyright (C) 2010 the original author or authors. + * See the notice.md file distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed 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 com.beust.jcommander.converters; + +import com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameter; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +@Test +public class ISO8601LocalDateConverterTest { + + @Test + public void testDateTime() { + class Arg { + @Parameter(names = "-datetime", converter = ISO8601LocalDateConverter.class) + LocalDate date; + } + String format = "hhmm"; + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format); + LocalDate dateNow = LocalDate.parse(formatter.format(LocalDate.now())); + Arg command = new Arg(); + JCommander jc = JCommander.newBuilder().addObject(command).build(); + jc.parse("-datetime", dateNow.format(DateTimeFormatter.ofPattern(format))); + + Assert.assertEquals(command.date, dateNow); + } + +}