diff --git a/src/main/java/com/cedarsoftware/util/Converter.java b/src/main/java/com/cedarsoftware/util/Converter.java index ec3a4724..8c6a6f27 100644 --- a/src/main/java/com/cedarsoftware/util/Converter.java +++ b/src/main/java/com/cedarsoftware/util/Converter.java @@ -455,10 +455,8 @@ public static AtomicBoolean convertToAtomicBoolean(Object fromInstance) /** * @param localDate A Java LocalDate - * @return a long representing the localDate as the number of milliseconds since the - * number of milliseconds since Jan 1, 1970 + * @return a long representing the localDate as epoch milliseconds (since 1970 Jan 1 at midnight) */ - public static long localDateToMillis(LocalDate localDate) { return instance.convert(localDate, long.class); @@ -466,8 +464,7 @@ public static long localDateToMillis(LocalDate localDate) /** * @param localDateTime A Java LocalDateTime - * @return a long representing the localDateTime as the number of milliseconds since the - * number of milliseconds since Jan 1, 1970 + * @return a long representing the localDateTime as epoch milliseconds (since 1970 Jan 1 at midnight) */ public static long localDateTimeToMillis(LocalDateTime localDateTime) { @@ -476,8 +473,7 @@ public static long localDateTimeToMillis(LocalDateTime localDateTime) /** * @param zonedDateTime A Java ZonedDateTime - * @return a long representing the zonedDateTime as the number of milliseconds since the - * number of milliseconds since Jan 1, 1970 + * @return a long representing the ZonedDateTime as epoch milliseconds (since 1970 Jan 1 at midnight) */ public static long zonedDateTimeToMillis(ZonedDateTime zonedDateTime) { diff --git a/src/main/java/com/cedarsoftware/util/convert/Converter.java b/src/main/java/com/cedarsoftware/util/convert/Converter.java index 3be35b19..99129939 100644 --- a/src/main/java/com/cedarsoftware/util/convert/Converter.java +++ b/src/main/java/com/cedarsoftware/util/convert/Converter.java @@ -14,7 +14,9 @@ import java.time.MonthDay; import java.time.OffsetDateTime; import java.time.OffsetTime; +import java.time.Period; import java.time.Year; +import java.time.YearMonth; import java.time.ZonedDateTime; import java.util.AbstractMap; import java.util.Calendar; @@ -640,6 +642,8 @@ private static void buildFactoryConversions() { DEFAULT_FACTORY.put(pair(Instant.class, String.class), StringConversions::toString); DEFAULT_FACTORY.put(pair(LocalTime.class, String.class), StringConversions::toString); DEFAULT_FACTORY.put(pair(MonthDay.class, String.class), StringConversions::toString); + DEFAULT_FACTORY.put(pair(YearMonth.class, String.class), StringConversions::toString); + DEFAULT_FACTORY.put(pair(Period.class, String.class), StringConversions::toString); DEFAULT_FACTORY.put(pair(OffsetTime.class, String.class), OffsetTimeConversions::toString); DEFAULT_FACTORY.put(pair(OffsetDateTime.class, String.class), OffsetDateTimeConversions::toString); DEFAULT_FACTORY.put(pair(Year.class, String.class), YearConversions::toString); @@ -670,8 +674,6 @@ private static void buildFactoryConversions() { DEFAULT_FACTORY.put(pair(Map.class, Instant.class), MapConversions::toInstant); DEFAULT_FACTORY.put(pair(OffsetDateTime.class, Instant.class), OffsetDateTimeConversions::toInstant); -// java.time.Period = com.cedarsoftware.util.io.DEFAULT_FACTORY.PeriodFactory -// java.time.YearMonth = com.cedarsoftware.util.io.DEFAULT_FACTORY.YearMonthFactory // java.time.ZoneId = com.cedarsoftware.util.io.DEFAULT_FACTORY.ZoneIdFactory // java.time.ZoneOffset = com.cedarsoftware.util.io.DEFAULT_FACTORY.ZoneOffsetFactory // java.time.ZoneRegion = com.cedarsoftware.util.io.DEFAULT_FACTORY.ZoneIdFactory @@ -682,6 +684,18 @@ private static void buildFactoryConversions() { DEFAULT_FACTORY.put(pair(String.class, MonthDay.class), StringConversions::toMonthDay); DEFAULT_FACTORY.put(pair(Map.class, MonthDay.class), MapConversions::toMonthDay); + // YearMonth conversions supported + DEFAULT_FACTORY.put(pair(Void.class, YearMonth.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(YearMonth.class, YearMonth.class), Converter::identity); + DEFAULT_FACTORY.put(pair(String.class, YearMonth.class), StringConversions::toYearMonth); + DEFAULT_FACTORY.put(pair(Map.class, YearMonth.class), MapConversions::toYearMonth); + + // Period conversions supported + DEFAULT_FACTORY.put(pair(Void.class, Period.class), VoidConversions::toNull); + DEFAULT_FACTORY.put(pair(Period.class, Period.class), Converter::identity); + DEFAULT_FACTORY.put(pair(String.class, Period.class), StringConversions::toPeriod); + DEFAULT_FACTORY.put(pair(Map.class, Period.class), MapConversions::toPeriod); + // toStringBuffer DEFAULT_FACTORY.put(pair(Void.class, StringBuffer.class), VoidConversions::toNull); DEFAULT_FACTORY.put(pair(String.class, StringBuffer.class), StringConversions::toStringBuffer); @@ -777,6 +791,8 @@ private static void buildFactoryConversions() { DEFAULT_FACTORY.put(pair(Instant.class, Map.class), InstantConversions::toMap); DEFAULT_FACTORY.put(pair(LocalTime.class, Map.class), LocalTimeConversions::toMap); DEFAULT_FACTORY.put(pair(MonthDay.class, Map.class), MonthDayConversions::toMap); + DEFAULT_FACTORY.put(pair(YearMonth.class, Map.class), YearMonthConversions::toMap); + DEFAULT_FACTORY.put(pair(Period.class, Map.class), PeriodConversions::toMap); DEFAULT_FACTORY.put(pair(Class.class, Map.class), MapConversions::initMap); DEFAULT_FACTORY.put(pair(UUID.class, Map.class), MapConversions::initMap); DEFAULT_FACTORY.put(pair(Calendar.class, Map.class), MapConversions::initMap); diff --git a/src/main/java/com/cedarsoftware/util/convert/MapConversions.java b/src/main/java/com/cedarsoftware/util/convert/MapConversions.java index 86a9e488..07f0ad12 100644 --- a/src/main/java/com/cedarsoftware/util/convert/MapConversions.java +++ b/src/main/java/com/cedarsoftware/util/convert/MapConversions.java @@ -11,7 +11,9 @@ import java.time.MonthDay; import java.time.OffsetDateTime; import java.time.OffsetTime; +import java.time.Period; import java.time.Year; +import java.time.YearMonth; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.util.Calendar; @@ -53,8 +55,11 @@ public final class MapConversions { private static final String TIME = "time"; private static final String ZONE = "zone"; private static final String YEAR = "year"; + private static final String YEARS = "years"; private static final String MONTH = "month"; + private static final String MONTHS = "months"; private static final String DAY = "day"; + private static final String DAYS = "days"; private static final String HOUR = "hour"; private static final String MINUTE = "minute"; private static final String SECOND = "second"; @@ -286,7 +291,7 @@ static Instant toInstant(Object from, Converter converter, ConverterOptions opti private static final String[] MONTH_DAY_PARAMS = new String[] { MONTH, DAY }; static MonthDay toMonthDay(Object from, Converter converter, ConverterOptions options) { Map map = (Map) from; - if (map.containsKey(MONTH)) { + if (map.containsKey(MONTH) && map.containsKey(DAY)) { int month = converter.convert(map.get(MONTH), int.class, options); int day = converter.convert(map.get(DAY), int.class, options); return MonthDay.of(month, day); @@ -295,6 +300,31 @@ static MonthDay toMonthDay(Object from, Converter converter, ConverterOptions op } } + private static final String[] YEAR_MONTH_PARAMS = new String[] { YEAR, MONTH }; + static YearMonth toYearMonth(Object from, Converter converter, ConverterOptions options) { + Map map = (Map) from; + if (map.containsKey(YEAR) && map.containsKey(MONTH)) { + int year = converter.convert(map.get(YEAR), int.class, options); + int month = converter.convert(map.get(MONTH), int.class, options); + return YearMonth.of(year, month); + } else { + return fromValueForMultiKey(from, converter, options, YearMonth.class, YEAR_MONTH_PARAMS); + } + } + + private static final String[] PERIOD_PARAMS = new String[] { YEARS, MONTHS, DAYS }; + static Period toPeriod(Object from, Converter converter, ConverterOptions options) { + Map map = (Map) from; + if (map.containsKey(YEARS) && map.containsKey(MONTHS) && map.containsKey(DAYS)) { + int years = converter.convert(map.get(YEARS), int.class, options); + int months = converter.convert(map.get(MONTHS), int.class, options); + int days = converter.convert(map.get(DAYS), int.class, options); + return Period.of(years, months, days); + } else { + return fromValueForMultiKey(from, converter, options, Period.class, PERIOD_PARAMS); + } + } + static Year toYear(Object from, Converter converter, ConverterOptions options) { return fromSingleKey(from, converter, options, YEAR, Year.class); } diff --git a/src/main/java/com/cedarsoftware/util/convert/PeriodConversions.java b/src/main/java/com/cedarsoftware/util/convert/PeriodConversions.java new file mode 100644 index 00000000..167895e7 --- /dev/null +++ b/src/main/java/com/cedarsoftware/util/convert/PeriodConversions.java @@ -0,0 +1,37 @@ +package com.cedarsoftware.util.convert; + +import java.time.Period; +import java.util.Map; + +import com.cedarsoftware.util.CompactLinkedMap; + +/** + * @author John DeRegnaucourt (jdereg@gmail.com) + *
+ * Copyright (c) Cedar Software LLC + *

+ * 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 + *

+ * License + *

+ * 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. + */ +public final class PeriodConversions { + + private PeriodConversions() {} + + static Map toMap(Object from, Converter converter, ConverterOptions options) { + Period period = (Period) from; + Map target = new CompactLinkedMap<>(); + target.put("years", period.getYears()); + target.put("months", period.getMonths()); + target.put("days", period.getDays()); + return target; + } +} diff --git a/src/main/java/com/cedarsoftware/util/convert/StringConversions.java b/src/main/java/com/cedarsoftware/util/convert/StringConversions.java index d189d143..c940a7ce 100644 --- a/src/main/java/com/cedarsoftware/util/convert/StringConversions.java +++ b/src/main/java/com/cedarsoftware/util/convert/StringConversions.java @@ -14,9 +14,12 @@ import java.time.MonthDay; import java.time.OffsetDateTime; import java.time.OffsetTime; +import java.time.Period; import java.time.Year; +import java.time.YearMonth; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; @@ -278,7 +281,7 @@ static MonthDay toMonthDay(Object from, Converter converter, ConverterOptions op try { return MonthDay.parse(monthDay); } - catch (Exception e) { + catch (DateTimeParseException e) { Matcher matcher = MM_DD.matcher(monthDay); if (matcher.find()) { String mm = matcher.group(1); @@ -297,6 +300,27 @@ static MonthDay toMonthDay(Object from, Converter converter, ConverterOptions op } } + static YearMonth toYearMonth(Object from, Converter converter, ConverterOptions options) { + String yearMonth = (String) from; + try { + return YearMonth.parse(yearMonth); + } + catch (DateTimeParseException e) { + try { + ZonedDateTime zdt = DateUtilities.parseDate(yearMonth, options.getZoneId(), true); + return YearMonth.of(zdt.getYear(), zdt.getDayOfMonth()); + } + catch (Exception ex) { + throw new IllegalArgumentException("Unable to extract Year-Month from string: " + yearMonth); + } + } + } + + static Period toPeriod(Object from, Converter converter, ConverterOptions options) { + String period = (String) from; + return Period.parse(period); + } + static Date toDate(Object from, Converter converter, ConverterOptions options) { Instant instant = getInstant((String) from, options); if (instant == null) { diff --git a/src/main/java/com/cedarsoftware/util/convert/YearMonthConversions.java b/src/main/java/com/cedarsoftware/util/convert/YearMonthConversions.java new file mode 100644 index 00000000..6ce23cce --- /dev/null +++ b/src/main/java/com/cedarsoftware/util/convert/YearMonthConversions.java @@ -0,0 +1,36 @@ +package com.cedarsoftware.util.convert; + +import java.time.YearMonth; +import java.util.Map; + +import com.cedarsoftware.util.CompactLinkedMap; + +/** + * @author John DeRegnaucourt (jdereg@gmail.com) + *
+ * Copyright (c) Cedar Software LLC + *

+ * 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 + *

+ * License + *

+ * 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. + */ +public final class YearMonthConversions { + + private YearMonthConversions() {} + + static Map toMap(Object from, Converter converter, ConverterOptions options) { + YearMonth yearMonth = (YearMonth) from; + Map target = new CompactLinkedMap<>(); + target.put("year", yearMonth.getYear()); + target.put("month", yearMonth.getMonthValue()); + return target; + } +}