JUNEAU-101 Update handling of dates to use new Java 8 libraries.
diff --git a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/transforms/TemporalCalendarSwapTest.java b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/transforms/TemporalCalendarSwapTest.java
index f3bfec3..608ddff 100644
--- a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/transforms/TemporalCalendarSwapTest.java
+++ b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/transforms/TemporalCalendarSwapTest.java
@@ -68,14 +68,14 @@
"[0] BasicIsoDate, Default timezone",
T_Calendar,
new TemporalCalendarSwap.BasicIsoDate(),
- "20121221",
+ "20121221-0500",
BS_DEFAULT
},
{
"[1] BasicIsoDate, Pacific timezone",
T_Calendar,
new TemporalCalendarSwap.BasicIsoDate(),
- "20121221",
+ "20121221-0500",
BS_PST
},
@@ -337,14 +337,14 @@
{
"[30] YEAR, Default timezone",
T_Calendar,
- new TemporalCalendarSwap("uuuu", Year.class, false, false),
+ new TemporalCalendarSwap("uuuu"),
"2012",
BS_DEFAULT
},
{
"[31] YEAR, Pacific timezone",
T_Calendar,
- new TemporalCalendarSwap("uuuu", Year.class, false, false),
+ new TemporalCalendarSwap("uuuu"),
"2012",
BS_DEFAULT
},
diff --git a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/transforms/TemporalDateSwapTest.java b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/transforms/TemporalDateSwapTest.java
index 6907f40..9986cfc 100644
--- a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/transforms/TemporalDateSwapTest.java
+++ b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/transforms/TemporalDateSwapTest.java
@@ -65,14 +65,14 @@
"[0] BasicIsoDate, Default timezone",
T_Date,
new TemporalDateSwap.BasicIsoDate(),
- "20121221",
+ "20121221-0500",
BS_DEFAULT
},
{
"[1] BasicIsoDate, Pacific timezone",
T_Date,
new TemporalDateSwap.BasicIsoDate(),
- "20121221",
+ "20121221-0800",
BS_PST
},
@@ -334,14 +334,14 @@
{
"[30] YEAR, Default timezone",
T_Date,
- new TemporalDateSwap("uuuu", Year.class, false),
+ new TemporalDateSwap("uuuu"),
"2012",
BS_DEFAULT
},
{
"[31] YEAR, Pacific timezone",
T_Date,
- new TemporalDateSwap("uuuu", Year.class, false),
+ new TemporalDateSwap("uuuu"),
"2012",
BS_DEFAULT
},
diff --git a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/transforms/TemporalSwapTest.java b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/transforms/TemporalSwapTest.java
index 7a860d5..6812521 100644
--- a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/transforms/TemporalSwapTest.java
+++ b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/transforms/TemporalSwapTest.java
@@ -81,14 +81,14 @@
"[0] BasicIsoDate, DT_ZonedDateTime, Default timezone",
DT_ZonedDateTime,
new TemporalSwap.BasicIsoDate(),
- "20121221",
+ "20121221Z",
BS_DEFAULT
},
{
"[1] BasicIsoDate, DT_Instant, Default timezone",
DT_Instant,
new TemporalSwap.BasicIsoDate(),
- "20121221",
+ "20121221Z",
BS_DEFAULT
},
{
@@ -116,14 +116,14 @@
"[5] BasicIsoDate, DT_OffsetDateTime, Default timezone",
DT_OffsetDateTime,
new TemporalSwap.BasicIsoDate(),
- "20121221",
+ "20121221-0500",
BS_DEFAULT
},
{
"[6] BasicIsoDate, DT_OffsetTime, Default timezone",
DT_OffsetTime,
new TemporalSwap.BasicIsoDate(),
- "19700101",
+ "19700101-0500",
BS_DEFAULT
},
{
@@ -177,14 +177,14 @@
"[13] BasicIsoDate, DT_ZonedDateTime, PST timezone",
DT_ZonedDateTime,
new TemporalSwap.BasicIsoDate(),
- "20121221",
+ "20121221Z",
BS_PST
},
{
"[14] BasicIsoDate, DT_Instant, PST timezone",
DT_Instant,
new TemporalSwap.BasicIsoDate(),
- "20121221",
+ "20121221Z",
BS_PST
},
{
@@ -212,14 +212,14 @@
"[18] BasicIsoDate, DT_OffsetDateTime, PST timezone",
DT_OffsetDateTime,
new TemporalSwap.BasicIsoDate(),
- "20121221",
+ "20121221-0500",
BS_PST
},
{
"[19] BasicIsoDate, DT_OffsetTime, PST timezone",
DT_OffsetTime,
new TemporalSwap.BasicIsoDate(),
- "19700101",
+ "19700101-0500",
BS_PST
},
{
@@ -279,7 +279,7 @@
"[27] IsoDate, DT_Instant, Default timezone",
DT_Instant,
new TemporalSwap.IsoDate(),
- "2012-12-21",
+ "2012-12-21Z",
BS_DEFAULT
},
{
@@ -314,7 +314,7 @@
"[32] IsoDate, DT_OffsetTime, Default timezone",
DT_OffsetTime,
new TemporalSwap.IsoDate(),
- "1970-01-01",
+ "1970-01-01-05:00",
BS_DEFAULT
},
{
@@ -374,7 +374,7 @@
"[40] IsoDate, DT_Instant, PST timezone",
DT_Instant,
new TemporalSwap.IsoDate(),
- "2012-12-21",
+ "2012-12-21Z",
BS_PST
},
{
@@ -409,7 +409,7 @@
"[45] IsoDate, DT_OffsetTime, PST timezone",
DT_OffsetTime,
new TemporalSwap.IsoDate(),
- "1970-01-01",
+ "1970-01-01-05:00",
BS_PST
},
{
@@ -469,28 +469,28 @@
"[53] IsoDateTime, DT_Instant, Default timezone",
DT_Instant,
new TemporalSwap.IsoDateTime(),
- "2012-12-21T07:34:56-05:00[GMT-05:00]",
+ "2012-12-21T12:34:56Z",
BS_DEFAULT
},
{
"[54] IsoDateTime, DT_LocalDate, Default timezone",
DT_LocalDate,
new TemporalSwap.IsoDateTime(),
- "2012-12-21T00:00:00-05:00[GMT-05:00]",
+ "2012-12-21T00:00:00",
BS_DEFAULT
},
{
"[55] IsoDateTime, DT_LocalDateTime, Default timezone",
DT_LocalDateTime,
new TemporalSwap.IsoDateTime(),
- "2012-12-21T12:34:56-05:00[GMT-05:00]",
+ "2012-12-21T12:34:56",
BS_DEFAULT
},
{
"[56] IsoDateTime, DT_LocalTime, Default timezone",
DT_LocalTime,
new TemporalSwap.IsoDateTime(),
- "1970-01-01T12:34:56-05:00[GMT-05:00]",
+ "1970-01-01T12:34:56",
BS_DEFAULT
},
{
@@ -511,42 +511,42 @@
"[59] IsoDateTime, DT_Year, Default timezone",
DT_Year,
new TemporalSwap.IsoDateTime(),
- "2012-01-01T00:00:00-05:00[GMT-05:00]",
+ "2012-01-01T00:00:00",
BS_DEFAULT
},
{
"[60] IsoDateTime, DT_YearMonth, Default timezone",
DT_YearMonth,
new TemporalSwap.IsoDateTime(),
- "2012-12-01T00:00:00-05:00[GMT-05:00]",
+ "2012-12-01T00:00:00",
BS_DEFAULT
},
{
"[61] IsoDateTime, DT_HijrahDate, Default timezone",
DT_HijrahDate,
new TemporalSwap.IsoDateTime(),
- "2012-12-21T00:00:00-05:00[GMT-05:00]",
+ "2012-12-21T00:00:00",
BS_DEFAULT
},
{
"[62] IsoDateTime, DT_JapaneseDate, Default timezone",
DT_JapaneseDate,
new TemporalSwap.IsoDateTime(),
- "2012-12-21T00:00:00-05:00[GMT-05:00]",
+ "2012-12-21T00:00:00",
BS_DEFAULT
},
{
"[63] IsoDateTime, DT_MinguoDate, Default timezone",
DT_MinguoDate,
new TemporalSwap.IsoDateTime(),
- "2012-12-21T00:00:00-05:00[GMT-05:00]",
+ "2012-12-21T00:00:00",
BS_DEFAULT
},
{
"[64] IsoDateTime, DT_ThaiBuddhistDate, Default timezone",
DT_ThaiBuddhistDate,
new TemporalSwap.IsoDateTime(),
- "2012-12-21T00:00:00-05:00[GMT-05:00]",
+ "2012-12-21T00:00:00",
BS_DEFAULT
},
@@ -564,28 +564,28 @@
"[66] IsoDateTime, DT_Instant, PST timezone",
DT_Instant,
new TemporalSwap.IsoDateTime(),
- "2012-12-21T04:34:56-08:00[America/Los_Angeles]",
+ "2012-12-21T12:34:56Z",
BS_PST
},
{
"[67] IsoDateTime, DT_LocalDate, PST timezone",
DT_LocalDate,
new TemporalSwap.IsoDateTime(),
- "2012-12-21T00:00:00-08:00[America/Los_Angeles]",
+ "2012-12-21T00:00:00",
BS_PST
},
{
"[68] IsoDateTime, DT_LocalDateTime, PST timezone",
DT_LocalDateTime,
new TemporalSwap.IsoDateTime(),
- "2012-12-21T12:34:56-08:00[America/Los_Angeles]",
+ "2012-12-21T12:34:56",
BS_PST
},
{
"[69] IsoDateTime, DT_LocalTime, PST timezone",
DT_LocalTime,
new TemporalSwap.IsoDateTime(),
- "1970-01-01T12:34:56-08:00[America/Los_Angeles]",
+ "1970-01-01T12:34:56",
BS_PST
},
{
@@ -606,42 +606,42 @@
"[72] IsoDateTime, DT_Year, PST timezone",
DT_Year,
new TemporalSwap.IsoDateTime(),
- "2012-01-01T00:00:00-08:00[America/Los_Angeles]",
+ "2012-01-01T00:00:00",
BS_PST
},
{
"[73] IsoDateTime, DT_YearMonth, PST timezone",
DT_YearMonth,
new TemporalSwap.IsoDateTime(),
- "2012-12-01T00:00:00-08:00[America/Los_Angeles]",
+ "2012-12-01T00:00:00",
BS_PST
},
{
"[74] IsoDateTime, DT_HijrahDate, PST timezone",
DT_HijrahDate,
new TemporalSwap.IsoDateTime(),
- "2012-12-21T00:00:00-08:00[America/Los_Angeles]",
+ "2012-12-21T00:00:00",
BS_PST
},
{
"[75] IsoDateTime, DT_JapaneseDate, PST timezone",
DT_JapaneseDate,
new TemporalSwap.IsoDateTime(),
- "2012-12-21T00:00:00-08:00[America/Los_Angeles]",
+ "2012-12-21T00:00:00",
BS_PST
},
{
"[76] IsoDateTime, DT_MinguoDate, PST timezone",
DT_MinguoDate,
new TemporalSwap.IsoDateTime(),
- "2012-12-21T00:00:00-08:00[America/Los_Angeles]",
+ "2012-12-21T00:00:00",
BS_PST
},
{
"[77] IsoDateTime, DT_ThaiBuddhistDate, PST timezone",
DT_ThaiBuddhistDate,
new TemporalSwap.IsoDateTime(),
- "2012-12-21T00:00:00-08:00[America/Los_Angeles]",
+ "2012-12-21T00:00:00",
BS_PST
},
@@ -1039,7 +1039,7 @@
"[131] IsoLocalDateTime, DT_Instant, Default timezone",
DT_Instant,
new TemporalSwap.IsoLocalDateTime(),
- "2012-12-21T07:34:56",
+ "2012-12-21T12:34:56",
BS_DEFAULT
},
{
@@ -1134,7 +1134,7 @@
"[144] IsoLocalDateTime, DT_Instant, PST timezone",
DT_Instant,
new TemporalSwap.IsoLocalDateTime(),
- "2012-12-21T04:34:56",
+ "2012-12-21T12:34:56",
BS_PST
},
{
@@ -1229,7 +1229,7 @@
"[157] IsoLocalTime, DT_Instant, Default timezone",
DT_Instant,
new TemporalSwap.IsoLocalTime(),
- "07:34:56",
+ "12:34:56",
BS_DEFAULT
},
{
@@ -1324,7 +1324,7 @@
"[170] IsoLocalTime, DT_Instant, PST timezone",
DT_Instant,
new TemporalSwap.IsoLocalTime(),
- "04:34:56",
+ "12:34:56",
BS_PST
},
{
@@ -1419,7 +1419,7 @@
"[183] IsoOffsetDate, DT_Instant, Default timezone",
DT_Instant,
new TemporalSwap.IsoOffsetDate(),
- "2012-12-21-05:00",
+ "2012-12-21Z",
BS_DEFAULT
},
{
@@ -1514,7 +1514,7 @@
"[196] IsoOffsetDate, DT_Instant, PST timezone",
DT_Instant,
new TemporalSwap.IsoOffsetDate(),
- "2012-12-21-08:00",
+ "2012-12-21Z",
BS_PST
},
{
@@ -1609,7 +1609,7 @@
"[209] IsoOffsetDateTime, DT_Instant, Default timezone",
DT_Instant,
new TemporalSwap.IsoOffsetDateTime(),
- "2012-12-21T07:34:56-05:00",
+ "2012-12-21T12:34:56Z",
BS_DEFAULT
},
{
@@ -1704,7 +1704,7 @@
"[222] IsoOffsetDateTime, DT_Instant, PST timezone",
DT_Instant,
new TemporalSwap.IsoOffsetDateTime(),
- "2012-12-21T04:34:56-08:00",
+ "2012-12-21T12:34:56Z",
BS_PST
},
{
@@ -1799,7 +1799,7 @@
"[235] IsoOffsetTime, DT_Instant, Default timezone",
DT_Instant,
new TemporalSwap.IsoOffsetTime(),
- "07:34:56-05:00",
+ "12:34:56Z",
BS_DEFAULT
},
{
@@ -1894,7 +1894,7 @@
"[248] IsoOffsetTime, DT_Instant, PST timezone",
DT_Instant,
new TemporalSwap.IsoOffsetTime(),
- "04:34:56-08:00",
+ "12:34:56Z",
BS_PST
},
{
@@ -1989,7 +1989,7 @@
"[261] IsoOrdinalDate, DT_Instant, Default timezone",
DT_Instant,
new TemporalSwap.IsoOrdinalDate(),
- "2012-356",
+ "2012-356Z",
BS_DEFAULT
},
{
@@ -2024,7 +2024,7 @@
"[266] IsoOrdinalDate, DT_OffsetTime, Default timezone",
DT_OffsetTime,
new TemporalSwap.IsoOrdinalDate(),
- "1970-001",
+ "1970-001-05:00",
BS_DEFAULT
},
{
@@ -2084,7 +2084,7 @@
"[274] IsoOrdinalDate, DT_Instant, PST timezone",
DT_Instant,
new TemporalSwap.IsoOrdinalDate(),
- "2012-356",
+ "2012-356Z",
BS_PST
},
{
@@ -2119,7 +2119,7 @@
"[279] IsoOrdinalDate, DT_OffsetTime, PST timezone",
DT_OffsetTime,
new TemporalSwap.IsoOrdinalDate(),
- "1970-001",
+ "1970-001-05:00",
BS_PST
},
{
@@ -2179,21 +2179,21 @@
"[287] IsoTime, DT_Instant, Default timezone",
DT_Instant,
new TemporalSwap.IsoTime(),
- "07:34:56-05:00",
+ "12:34:56Z",
BS_DEFAULT
},
{
"[288] IsoTime, DT_LocalDate, Default timezone",
DT_LocalDate,
new TemporalSwap.IsoTime(),
- "00:00:00-05:00",
+ "00:00:00",
BS_DEFAULT
},
{
"[289] IsoTime, DT_LocalDateTime, Default timezone",
DT_LocalDateTime,
new TemporalSwap.IsoTime(),
- "12:34:56-05:00",
+ "12:34:56",
BS_DEFAULT
},
{
@@ -2221,42 +2221,42 @@
"[293] IsoTime, DT_Year, Default timezone",
DT_Year,
new TemporalSwap.IsoTime(),
- "00:00:00-05:00",
+ "00:00:00",
BS_DEFAULT
},
{
"[294] IsoTime, DT_YearMonth, Default timezone",
DT_YearMonth,
new TemporalSwap.IsoTime(),
- "00:00:00-05:00",
+ "00:00:00",
BS_DEFAULT
},
{
"[295] IsoTime, DT_HijrahDate, Default timezone",
DT_HijrahDate,
new TemporalSwap.IsoTime(),
- "00:00:00-05:00",
+ "00:00:00",
BS_DEFAULT
},
{
"[296] IsoTime, DT_JapaneseDate, Default timezone",
DT_JapaneseDate,
new TemporalSwap.IsoTime(),
- "00:00:00-05:00",
+ "00:00:00",
BS_DEFAULT
},
{
"[297] IsoTime, DT_MinguoDate, Default timezone",
DT_MinguoDate,
new TemporalSwap.IsoTime(),
- "00:00:00-05:00",
+ "00:00:00",
BS_DEFAULT
},
{
"[298] IsoTime, DT_ThaiBuddhistDate, Default timezone",
DT_ThaiBuddhistDate,
new TemporalSwap.IsoTime(),
- "00:00:00-05:00",
+ "00:00:00",
BS_DEFAULT
},
@@ -2274,21 +2274,21 @@
"[300] IsoTime, DT_Instant, PST timezone",
DT_Instant,
new TemporalSwap.IsoTime(),
- "04:34:56-08:00",
+ "12:34:56Z",
BS_PST
},
{
"[301] IsoTime, DT_LocalDate, PST timezone",
DT_LocalDate,
new TemporalSwap.IsoTime(),
- "00:00:00-08:00",
+ "00:00:00",
BS_PST
},
{
"[302] IsoTime, DT_LocalDateTime, PST timezone",
DT_LocalDateTime,
new TemporalSwap.IsoTime(),
- "12:34:56-08:00",
+ "12:34:56",
BS_PST
},
{
@@ -2316,42 +2316,42 @@
"[306] IsoTime, DT_Year, PST timezone",
DT_Year,
new TemporalSwap.IsoTime(),
- "00:00:00-08:00",
+ "00:00:00",
BS_PST
},
{
"[307] IsoTime, DT_YearMonth, PST timezone",
DT_YearMonth,
new TemporalSwap.IsoTime(),
- "00:00:00-08:00",
+ "00:00:00",
BS_PST
},
{
"[308] IsoTime, DT_HijrahDate, PST timezone",
DT_HijrahDate,
new TemporalSwap.IsoTime(),
- "00:00:00-08:00",
+ "00:00:00",
BS_PST
},
{
"[309] IsoTime, DT_JapaneseDate, PST timezone",
DT_JapaneseDate,
new TemporalSwap.IsoTime(),
- "00:00:00-08:00",
+ "00:00:00",
BS_PST
},
{
"[310] IsoTime, DT_MinguoDate, PST timezone",
DT_MinguoDate,
new TemporalSwap.IsoTime(),
- "00:00:00-08:00",
+ "00:00:00",
BS_PST
},
{
"[311] IsoTime, DT_ThaiBuddhistDate, PST timezone",
DT_ThaiBuddhistDate,
new TemporalSwap.IsoTime(),
- "00:00:00-08:00",
+ "00:00:00",
BS_PST
},
@@ -2369,7 +2369,7 @@
"[313] IsoWeekDate, DT_Instant, Default timezone",
DT_Instant,
new TemporalSwap.IsoWeekDate(),
- "2012-W51-5",
+ "2012-W51-5Z",
BS_DEFAULT
},
{
@@ -2404,7 +2404,7 @@
"[318] IsoWeekDate, DT_OffsetTime, Default timezone",
DT_OffsetTime,
new TemporalSwap.IsoWeekDate(),
- "1970-W01-4",
+ "1970-W01-4-05:00",
BS_DEFAULT
},
{
@@ -2464,7 +2464,7 @@
"[326] IsoWeekDate, DT_Instant, PST timezone",
DT_Instant,
new TemporalSwap.IsoWeekDate(),
- "2012-W51-5",
+ "2012-W51-5Z",
BS_PST
},
{
@@ -2499,7 +2499,7 @@
"[331] IsoWeekDate, DT_OffsetTime, PST timezone",
DT_OffsetTime,
new TemporalSwap.IsoWeekDate(),
- "1970-W01-4",
+ "1970-W01-4-05:00",
BS_PST
},
{
@@ -2939,7 +2939,7 @@
"[391] IsoZonedDateTime, DT_Instant, Default timezone",
DT_Instant,
new TemporalSwap.IsoZonedDateTime(),
- "2012-12-21T07:34:56-05:00[GMT-05:00]",
+ "2012-12-21T12:34:56Z",
BS_DEFAULT
},
{
@@ -3034,7 +3034,7 @@
"[404] IsoZonedDateTime, DT_Instant, PST timezone",
DT_Instant,
new TemporalSwap.IsoZonedDateTime(),
- "2012-12-21T04:34:56-08:00[America/Los_Angeles]",
+ "2012-12-21T12:34:56Z",
BS_PST
},
{
@@ -3129,7 +3129,7 @@
"[417] Rfc1123DateTime, DT_Instant, Default timezone",
DT_Instant,
new TemporalSwap.Rfc1123DateTime(),
- "Fri, 21 Dec 2012 07:34:56 -0500",
+ "Fri, 21 Dec 2012 12:34:56 GMT",
BS_DEFAULT
},
{
@@ -3224,7 +3224,7 @@
"[430] Rfc1123DateTime, DT_Instant, PST timezone",
DT_Instant,
new TemporalSwap.Rfc1123DateTime(),
- "Fri, 21 Dec 2012 04:34:56 -0800",
+ "Fri, 21 Dec 2012 12:34:56 GMT",
BS_PST
},
{
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/DateUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/DateUtils.java
index 8db1995..b82d8bc 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/DateUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/DateUtils.java
@@ -16,10 +16,7 @@
import java.lang.ref.*;
import java.text.*;
-import java.time.*;
-import java.time.chrono.*;
import java.time.format.*;
-import java.time.temporal.*;
import java.util.*;
import javax.xml.bind.*;
@@ -292,7 +289,6 @@
}
}
-
/**
* Returns a {@link DateTimeFormatter} using either a pattern or predefined pattern name.
*
@@ -311,449 +307,4 @@
throw new RuntimeException(e);
}
}
-
- /**
- * Returns the specified {@link Temporal} object to an {@link Instant} object.
- *
- * @param t The temporal object to convert.
- * @param zoneId The time zone if not already included in temporal.
- * @return The timestamp.
- */
- public static Instant toInstant(Temporal t, ZoneId zoneId) {
- return toTemporal(t, Instant.class, zoneId);
- }
-
- /**
- * Returns the specified {@link Temporal} object to a {@link ZonedDateTime} object.
- *
- * @param t The temporal object to convert.
- * @param zoneId The time zone if not already included in temporal.
- * @return The timestamp.
- */
- public static ZonedDateTime toZonedDateTime(Temporal t, ZoneId zoneId) {
- return toTemporal(t, ZonedDateTime.class, zoneId);
- }
-
- /**
- * Returns the specified {@link Temporal} object to a {@link Date} object.
- *
- * @param t The temporal object to convert.
- * @param zoneId The time zone if not already included in temporal.
- * @return The date.
- */
- public static Date toDate(Temporal t, ZoneId zoneId) {
- return Date.from(toInstant(t, zoneId));
- }
-
- /**
- * Returns the specified {@link Temporal} object to a {@link Calendar} object.
- *
- * @param t The temporal object to convert.
- * @param zoneId The time zone if not already included in temporal.
- * @return The date.
- */
- public static Calendar toCalendar(Temporal t, ZoneId zoneId) {
- return GregorianCalendar.from(toZonedDateTime(t, zoneId));
- }
-
- private static final LocalDate ZERO_DATE = LocalDate.ofEpochDay(0);
- private static final MonthDay ZERO_MONTHDAY = MonthDay.of(1, 1);
- private static final LocalTime ZERO_TIME = LocalTime.MIDNIGHT;
-
- /**
- * Converts an arbitrary {@link Temporal} to another arbitrary {@link Temporal}
- *
- * @param o The temporal to convert.
- * @param tc The target temporal class.
- * @param zoneId The time zone if not already included in temporal.
- * @return The converted temporal.
- * @param <T> The target temporal class.
- */
- public static <T> T toTemporal(Temporal o, Class<T> tc, ZoneId zoneId) {
- if (o == null)
- return null;
- T t = toTemporal2(o, tc, zoneId);
- if (t.getClass() != tc)
- throw new RuntimeException("Temporal=["+o.getClass().getName()+"], wanted=["+tc.getName()+"], actual=["+t.getClass().getName()+"]");
- return t;
- }
-
- @SuppressWarnings("unchecked")
- private static <T> T toTemporal2(Temporal o, Class<T> tc, ZoneId zoneId) {
-
- if (o == null)
- return null;
-
- Class<? extends Temporal> oc = o.getClass();
-
- if (oc == tc)
- return (T)o;
-
- if (zoneId == null)
- zoneId = ZoneId.systemDefault();
-
- if (oc == Instant.class) {
- Instant t = (Instant)o;
- if (tc == LocalDate.class) {
- return (T)t.atZone(zoneId).toLocalDate();
- } else if (tc == LocalDateTime.class) {
- return (T)t.atZone(zoneId).toLocalDateTime();
- } else if (tc == LocalTime.class) {
- return (T)t.atZone(zoneId).toLocalTime();
- } else if (tc == OffsetDateTime.class) {
- return (T)t.atZone(zoneId).toOffsetDateTime();
- } else if (tc == OffsetTime.class) {
- return (T)t.atZone(zoneId).toOffsetDateTime().toOffsetTime();
- } else if (tc == Year.class) {
- return (T)Year.from(t.atZone(zoneId));
- } else if (tc == YearMonth.class) {
- return (T)YearMonth.from(t.atZone(zoneId));
- } else if (tc == ZonedDateTime.class) {
- return (T)t.atZone(zoneId);
- } else if (tc == HijrahDate.class) {
- return (T)HijrahDate.from(t.atZone(zoneId));
- } else if (tc == JapaneseDate.class) {
- return (T)JapaneseDate.from(t.atZone(zoneId));
- } else if (tc == MinguoDate.class) {
- return (T)MinguoDate.from(t.atZone(zoneId));
- } else if (tc == ThaiBuddhistDate.class) {
- return (T)ThaiBuddhistDate.from(t.atZone(zoneId));
- }
- } else if (oc == LocalDate.class) {
- LocalDate t = (LocalDate)o;
- if (tc == Instant.class) {
- return (T)t.atStartOfDay(zoneId).toInstant();
- } else if (tc == LocalDateTime.class) {
- return (T)t.atStartOfDay(zoneId).toLocalDateTime();
- } else if (tc == LocalTime.class) {
- return (T)t.atStartOfDay(zoneId).toLocalTime();
- } else if (tc == OffsetDateTime.class) {
- return (T)t.atStartOfDay(zoneId).toOffsetDateTime();
- } else if (tc == OffsetTime.class) {
- return (T)t.atStartOfDay(zoneId).toOffsetDateTime().toOffsetTime();
- } else if (tc == Year.class) {
- return (T)Year.from(t.atStartOfDay(zoneId));
- } else if (tc == YearMonth.class) {
- return (T)YearMonth.from(t.atStartOfDay(zoneId));
- } else if (tc == ZonedDateTime.class) {
- return (T)t.atStartOfDay(zoneId);
- } else if (tc == HijrahDate.class) {
- return (T)HijrahDate.from(t.atStartOfDay(zoneId));
- } else if (tc == JapaneseDate.class) {
- return (T)JapaneseDate.from(t.atStartOfDay(zoneId));
- } else if (tc == MinguoDate.class) {
- return (T)MinguoDate.from(t.atStartOfDay(zoneId));
- } else if (tc == ThaiBuddhistDate.class) {
- return (T)ThaiBuddhistDate.from(t.atStartOfDay(zoneId));
- }
- } else if (oc == LocalDateTime.class) {
- LocalDateTime t = (LocalDateTime)o;
- if (tc == Instant.class) {
- return (T)t.atZone(zoneId).toInstant();
- } else if (tc == LocalDate.class) {
- return (T)t.toLocalDate();
- } else if (tc == LocalTime.class) {
- return (T)t.toLocalTime();
- } else if (tc == OffsetDateTime.class) {
- return (T)t.atZone(zoneId).toOffsetDateTime();
- } else if (tc == OffsetTime.class) {
- return (T)t.atZone(zoneId).toOffsetDateTime().toOffsetTime();
- } else if (tc == Year.class) {
- return (T)Year.from(t.atZone(zoneId));
- } else if (tc == YearMonth.class) {
- return (T)YearMonth.from(t.atZone(zoneId));
- } else if (tc == ZonedDateTime.class) {
- return (T)t.atZone(zoneId);
- } else if (tc == HijrahDate.class) {
- return (T)HijrahDate.from(t.atZone(zoneId));
- } else if (tc == JapaneseDate.class) {
- return (T)JapaneseDate.from(t.atZone(zoneId));
- } else if (tc == MinguoDate.class) {
- return (T)MinguoDate.from(t.atZone(zoneId));
- } else if (tc == ThaiBuddhistDate.class) {
- return (T)ThaiBuddhistDate.from(t.atZone(zoneId));
- }
- } else if (oc == LocalTime.class) {
- LocalTime t = (LocalTime)o;
- if (tc == Instant.class) {
- return (T)t.atDate(ZERO_DATE).atZone(zoneId).toInstant();
- } else if (tc == LocalDate.class) {
- return (T)LocalDate.ofEpochDay(0);
- } else if (tc == LocalDateTime.class) {
- return (T)t.atDate(ZERO_DATE);
- } else if (tc == OffsetDateTime.class) {
- return (T)t.atDate(ZERO_DATE).atZone(zoneId).toOffsetDateTime();
- } else if (tc == OffsetTime.class) {
- return (T)t.atDate(ZERO_DATE).atZone(zoneId).toOffsetDateTime().toOffsetTime();
- } else if (tc == Year.class) {
- return (T)Year.of(1970);
- } else if (tc == YearMonth.class) {
- return (T)YearMonth.of(1970, 1);
- } else if (tc == ZonedDateTime.class) {
- return (T)t.atDate(ZERO_DATE).atZone(zoneId);
- } else if (tc == HijrahDate.class) {
- return (T)HijrahDate.from(ZERO_DATE.atStartOfDay(zoneId));
- } else if (tc == JapaneseDate.class) {
- return (T)JapaneseDate.from(ZERO_DATE.atStartOfDay(zoneId));
- } else if (tc == MinguoDate.class) {
- return (T)MinguoDate.from(ZERO_DATE.atStartOfDay(zoneId));
- } else if (tc == ThaiBuddhistDate.class) {
- return (T)ThaiBuddhistDate.from(ZERO_DATE.atStartOfDay(zoneId));
- }
- } else if (oc == OffsetDateTime.class) {
- OffsetDateTime t = (OffsetDateTime)o;
- if (tc == Instant.class) {
- return (T)t.toInstant();
- } else if (tc == LocalDate.class) {
- return (T)t.toLocalDate();
- } else if (tc == LocalDateTime.class) {
- return (T)t.toLocalDateTime();
- } else if (tc == LocalTime.class) {
- return (T)t.toLocalTime();
- } else if (tc == OffsetTime.class) {
- return (T)t.toOffsetTime();
- } else if (tc == Year.class) {
- return (T)Year.from(t);
- } else if (tc == YearMonth.class) {
- return (T)YearMonth.from(t);
- } else if (tc == ZonedDateTime.class) {
- return (T)t.toZonedDateTime();
- } else if (tc == HijrahDate.class) {
- return (T)HijrahDate.from(t);
- } else if (tc == JapaneseDate.class) {
- return (T)JapaneseDate.from(t);
- } else if (tc == MinguoDate.class) {
- return (T)MinguoDate.from(t);
- } else if (tc == ThaiBuddhistDate.class) {
- return (T)ThaiBuddhistDate.from(t);
- }
- } else if (oc == OffsetTime.class) {
- OffsetTime t = (OffsetTime)o;
- if (tc == Instant.class) {
- return (T)t.atDate(ZERO_DATE).toInstant();
- } else if (tc == LocalDate.class) {
- return (T)LocalDate.ofEpochDay(0);
- } else if (tc == LocalDateTime.class) {
- return (T)t.atDate(ZERO_DATE).toLocalDateTime();
- } else if (tc == LocalTime.class) {
- return (T)t.atDate(ZERO_DATE).toLocalTime();
- } else if (tc == OffsetDateTime.class) {
- return (T)t.atDate(ZERO_DATE);
- } else if (tc == Year.class) {
- return (T)Year.from(t.atDate(ZERO_DATE));
- } else if (tc == YearMonth.class) {
- return (T)YearMonth.from(t.atDate(ZERO_DATE));
- } else if (tc == ZonedDateTime.class) {
- return (T)t.atDate(ZERO_DATE).toZonedDateTime();
- } else if (tc == HijrahDate.class) {
- return (T)HijrahDate.from(t.atDate(ZERO_DATE));
- } else if (tc == JapaneseDate.class) {
- return (T)JapaneseDate.from(t.atDate(ZERO_DATE));
- } else if (tc == MinguoDate.class) {
- return (T)MinguoDate.from(t.atDate(ZERO_DATE));
- } else if (tc == ThaiBuddhistDate.class) {
- return (T)ThaiBuddhistDate.from(t.atDate(ZERO_DATE));
- }
- } else if (oc == Year.class) {
- Year t = (Year)o;
- if (tc == Instant.class) {
- return (T)t.atMonthDay(ZERO_MONTHDAY).atStartOfDay(zoneId).toInstant();
- } else if (tc == LocalDate.class) {
- return (T)t.atMonthDay(ZERO_MONTHDAY);
- } else if (tc == LocalDateTime.class) {
- return (T)t.atMonthDay(ZERO_MONTHDAY).atStartOfDay(zoneId).toLocalDateTime();
- } else if (tc == LocalTime.class) {
- return (T)ZERO_TIME;
- } else if (tc == OffsetDateTime.class) {
- return (T)t.atMonthDay(ZERO_MONTHDAY).atStartOfDay(zoneId).toOffsetDateTime();
- } else if (tc == OffsetTime.class) {
- return (T)t.atMonthDay(ZERO_MONTHDAY).atStartOfDay(zoneId).toOffsetDateTime().toOffsetTime();
- } else if (tc == YearMonth.class) {
- return (T)t.atMonth(1);
- } else if (tc == ZonedDateTime.class) {
- return (T)t.atMonthDay(ZERO_MONTHDAY).atStartOfDay(zoneId);
- } else if (tc == HijrahDate.class) {
- return (T)HijrahDate.from(t.atMonthDay(ZERO_MONTHDAY).atStartOfDay(zoneId));
- } else if (tc == JapaneseDate.class) {
- return (T)JapaneseDate.from(t.atMonthDay(ZERO_MONTHDAY).atStartOfDay(zoneId));
- } else if (tc == MinguoDate.class) {
- return (T)MinguoDate.from(t.atMonthDay(ZERO_MONTHDAY).atStartOfDay(zoneId));
- } else if (tc == ThaiBuddhistDate.class) {
- return (T)ThaiBuddhistDate.from(t.atMonthDay(ZERO_MONTHDAY).atStartOfDay(zoneId));
- }
- } else if (oc == YearMonth.class) {
- YearMonth t = (YearMonth)o;
- if (tc == Instant.class) {
- return (T)t.atDay(1).atStartOfDay(zoneId).toInstant();
- } else if (tc == LocalDate.class) {
- return (T)t.atDay(1).atStartOfDay(zoneId).toLocalDate();
- } else if (tc == LocalDateTime.class) {
- return (T)t.atDay(1).atStartOfDay(zoneId).toLocalDateTime();
- } else if (tc == LocalTime.class) {
- return (T)t.atDay(1).atStartOfDay(zoneId).toLocalTime();
- } else if (tc == OffsetDateTime.class) {
- return (T)t.atDay(1).atStartOfDay(zoneId).toOffsetDateTime();
- } else if (tc == OffsetTime.class) {
- return (T)t.atDay(1).atStartOfDay(zoneId).toOffsetDateTime().toOffsetTime();
- } else if (tc == Year.class) {
- return (T)Year.from(t);
- } else if (tc == ZonedDateTime.class) {
- return (T)t.atDay(1).atStartOfDay(zoneId);
- } else if (tc == HijrahDate.class) {
- return (T)HijrahDate.from(t.atDay(1).atStartOfDay(zoneId));
- } else if (tc == JapaneseDate.class) {
- return (T)JapaneseDate.from(t.atDay(1).atStartOfDay(zoneId));
- } else if (tc == MinguoDate.class) {
- return (T)MinguoDate.from(t.atDay(1).atStartOfDay(zoneId));
- } else if (tc == ThaiBuddhistDate.class) {
- return (T)ThaiBuddhistDate.from(t.atDay(1).atStartOfDay(zoneId));
- }
- } else if (oc == ZonedDateTime.class) {
- ZonedDateTime t = (ZonedDateTime)o;
- if (tc == Instant.class) {
- return (T)t.toInstant();
- } else if (tc == LocalDate.class) {
- return (T)t.toLocalDate();
- } else if (tc == LocalDateTime.class) {
- return (T)t.toLocalDateTime();
- } else if (tc == LocalTime.class) {
- return (T)t.toLocalTime();
- } else if (tc == OffsetDateTime.class) {
- return (T)t.toOffsetDateTime();
- } else if (tc == OffsetTime.class) {
- return (T)t.toOffsetDateTime().toOffsetTime();
- } else if (tc == Year.class) {
- return (T)Year.from(t);
- } else if (tc == YearMonth.class) {
- return (T)YearMonth.from(t);
- } else if (tc == HijrahDate.class) {
- return (T)HijrahDate.from(t);
- } else if (tc == JapaneseDate.class) {
- return (T)JapaneseDate.from(t);
- } else if (tc == MinguoDate.class) {
- return (T)MinguoDate.from(t);
- } else if (tc == ThaiBuddhistDate.class) {
- return (T)ThaiBuddhistDate.from(t);
- }
- } else if (oc == HijrahDate.class) {
- HijrahDate t = (HijrahDate)o;
- if (tc == Instant.class) {
- return (T)t.atTime(ZERO_TIME).atZone(zoneId).toInstant();
- } else if (tc == LocalDate.class) {
- return (T)LocalDate.ofEpochDay(t.toEpochDay());
- } else if (tc == LocalDateTime.class) {
- return (T)LocalDate.ofEpochDay(t.toEpochDay()).atTime(ZERO_TIME);
- } else if (tc == LocalTime.class) {
- return (T)ZERO_TIME;
- } else if (tc == OffsetDateTime.class) {
- return (T)t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId).toOffsetDateTime();
- } else if (tc == OffsetTime.class) {
- return (T)t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId).toOffsetDateTime().toOffsetTime();
- } else if (tc == Year.class) {
- return (T)Year.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- } else if (tc == YearMonth.class) {
- return (T)YearMonth.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- } else if (tc == ZonedDateTime.class) {
- return (T)t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId);
- } else if (tc == JapaneseDate.class) {
- return (T)JapaneseDate.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- } else if (tc == MinguoDate.class) {
- return (T)MinguoDate.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- } else if (tc == ThaiBuddhistDate.class) {
- return (T)ThaiBuddhistDate.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- }
- } else if (oc == JapaneseDate.class) {
- JapaneseDate t = (JapaneseDate)o;
- if (tc == Instant.class) {
- return (T)t.atTime(ZERO_TIME).atZone(zoneId).toInstant();
- } else if (tc == LocalDate.class) {
- return (T)LocalDate.ofEpochDay(t.toEpochDay());
- } else if (tc == LocalDateTime.class) {
- return (T)LocalDate.ofEpochDay(t.toEpochDay()).atTime(ZERO_TIME);
- } else if (tc == LocalTime.class) {
- return (T)ZERO_TIME;
- } else if (tc == OffsetDateTime.class) {
- return (T)t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId).toOffsetDateTime();
- } else if (tc == OffsetTime.class) {
- return (T)t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId).toOffsetDateTime().toOffsetTime();
- } else if (tc == Year.class) {
- return (T)Year.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- } else if (tc == YearMonth.class) {
- return (T)YearMonth.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- } else if (tc == ZonedDateTime.class) {
- return (T)t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId);
- } else if (tc == HijrahDate.class) {
- return (T)HijrahDate.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- } else if (tc == MinguoDate.class) {
- return (T)MinguoDate.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- } else if (tc == ThaiBuddhistDate.class) {
- return (T)ThaiBuddhistDate.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- }
- } else if (oc == MinguoDate.class) {
- MinguoDate t = (MinguoDate)o;
- if (tc == Instant.class) {
- return (T)t.atTime(ZERO_TIME).atZone(zoneId).toInstant();
- } else if (tc == LocalDate.class) {
- return (T)LocalDate.ofEpochDay(t.toEpochDay());
- } else if (tc == LocalDateTime.class) {
- return (T)LocalDate.ofEpochDay(t.toEpochDay()).atTime(ZERO_TIME);
- } else if (tc == LocalTime.class) {
- return (T)ZERO_TIME;
- } else if (tc == OffsetDateTime.class) {
- return (T)t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId).toOffsetDateTime();
- } else if (tc == OffsetTime.class) {
- return (T)t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId).toOffsetDateTime().toOffsetTime();
- } else if (tc == Year.class) {
- return (T)Year.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- } else if (tc == YearMonth.class) {
- return (T)YearMonth.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- } else if (tc == ZonedDateTime.class) {
- return (T)t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId);
- } else if (tc == HijrahDate.class) {
- return (T)HijrahDate.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- } else if (tc == JapaneseDate.class) {
- return (T)JapaneseDate.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- } else if (tc == ThaiBuddhistDate.class) {
- return (T)ThaiBuddhistDate.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- }
- } else if (oc == ThaiBuddhistDate.class) {
- ThaiBuddhistDate t = (ThaiBuddhistDate)o;
- if (tc == Instant.class) {
- return (T)t.atTime(ZERO_TIME).atZone(zoneId).toInstant();
- } else if (tc == LocalDate.class) {
- return (T)LocalDate.ofEpochDay(t.toEpochDay());
- } else if (tc == LocalDateTime.class) {
- return (T)LocalDate.ofEpochDay(t.toEpochDay()).atTime(ZERO_TIME);
- } else if (tc == LocalTime.class) {
- return (T)ZERO_TIME;
- } else if (tc == OffsetDateTime.class) {
- return (T)t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId).toOffsetDateTime();
- } else if (tc == OffsetTime.class) {
- return (T)t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId).toOffsetDateTime().toOffsetTime();
- } else if (tc == Year.class) {
- return (T)Year.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- } else if (tc == YearMonth.class) {
- return (T)YearMonth.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- } else if (tc == ZonedDateTime.class) {
- return (T)t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId);
- } else if (tc == HijrahDate.class) {
- return (T)HijrahDate.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- } else if (tc == JapaneseDate.class) {
- return (T)JapaneseDate.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- } else if (tc == MinguoDate.class) {
- return (T)MinguoDate.from(t.atTime(ZERO_TIME).atZone(zoneId).toInstant().atZone(zoneId));
- }
- }
-
- // Last chance...try to use a static from(TemporalAccessor) method if present.
- ClassInfo ci = ClassInfo.of(tc);
- MethodInfo mi = ci.getStaticPublicMethod("from", tc, TemporalAccessor.class);
- if (mi != null) {
- try {
- return (T)mi.inner().invoke(null, o);
- } catch (Exception e) {}
- }
-
- throw new RuntimeException("Temporal type '"+o.getClass().getName()+"' cannot be converted to type '"+tc.getName()+"'.");
- }
}
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/DefaultingTemporalAccessor.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/DefaultingTemporalAccessor.java
new file mode 100644
index 0000000..084a4b2
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/DefaultingTemporalAccessor.java
@@ -0,0 +1,142 @@
+// ***************************************************************************************************************************
+// * 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.juneau.transforms;
+
+import static java.time.temporal.ChronoField.*;
+import static java.time.temporal.TemporalQueries.*;
+
+import java.time.*;
+import java.time.format.*;
+import java.time.temporal.*;
+
+/**
+ * Wraps a {@link TemporalAccessor} to provide default values wherever possible instead of throwing unsupported field exceptions.
+ *
+ * <p>
+ * If working correctly, any <c>TemporalAccessor</c> returned by the {@link DateTimeFormatter#parse(CharSequence)} method
+ * should be able to be passed to any <code>Temporal.from(TemporalAccessor)</code> static method (such as {@link ZonedDateTime#from(TemporalAccessor)}).
+ */
+public class DefaultingTemporalAccessor implements TemporalAccessor {
+
+ private final TemporalAccessor inner;
+ private final ZoneId zoneId;
+ private ZonedDateTime zdt;
+
+ /**
+ * Constructor.
+ *
+ * @param inner The temporal accessor being wrapped.
+ * @param zoneId The default zone ID if it's not specified in the accessor.
+ */
+ public DefaultingTemporalAccessor(TemporalAccessor inner, ZoneId zoneId) {
+ this.inner = inner;
+ this.zoneId = zoneId;
+ }
+
+ @Override /* TemporalAccessor */
+ public boolean isSupported(TemporalField field) {
+ return inner.isSupported(field);
+ }
+
+ @Override /* TemporalAccessor */
+ @SuppressWarnings("unchecked")
+ public <R> R query(TemporalQuery<R> query) {
+ R r = inner.query(query);
+
+ if (r != null)
+ return r;
+
+ if (query == zone() || query == zoneId())
+ return (R)zoneId;
+
+ if (query == localTime()) {
+
+ if (isSupported(INSTANT_SECONDS))
+ return (R)zdt().toLocalTime();
+
+ int hour = 0;
+ if (isSupported(HOUR_OF_DAY))
+ hour = iget(HOUR_OF_DAY);
+ else if (isSupported(HOUR_OF_AMPM))
+ hour = iget(HOUR_OF_AMPM) + 12 * iget(AMPM_OF_DAY);
+
+ int minute = isSupported(MINUTE_OF_HOUR) ? iget(MINUTE_OF_HOUR) : 0;
+ int second = isSupported(SECOND_OF_MINUTE) ? iget(SECOND_OF_MINUTE) : 0;
+ int nano = isSupported(NANO_OF_SECOND) ? iget(NANO_OF_SECOND) : 0;
+
+ return (R)LocalTime.of(hour, minute, second, nano);
+ }
+
+ if (query == localDate()) {
+
+ if (isSupported(INSTANT_SECONDS))
+ return (R)zdt().toLocalDate();
+
+ int year = isSupported(YEAR) ? iget(ChronoField.YEAR) : 1970;
+ int month = isSupported(MONTH_OF_YEAR) ? iget(MONTH_OF_YEAR) : 1;
+ int dayOfMonth = isSupported(DAY_OF_MONTH) ? iget(DAY_OF_MONTH) : 1;
+
+ return (R)LocalDate.of(year, Month.of(month), dayOfMonth);
+ }
+
+ if (query == offset()) {
+ return (R)zoneId.getRules().getOffset(zdt().toInstant());
+ }
+
+ return null;
+ }
+
+ @Override /* TemporalAccessor */
+ public long getLong(TemporalField field) {
+
+ if (isSupported(field))
+ return inner.getLong(field);
+
+ if (field == INSTANT_SECONDS)
+ return zdt().toEpochSecond();
+
+ if (field == EPOCH_DAY)
+ return zdt().toLocalDate().toEpochDay();
+
+ if (field == YEAR) {
+ if (isSupported(INSTANT_SECONDS))
+ return zdt().toLocalDate().getYear();
+ return 1970;
+ }
+
+ if (field == MONTH_OF_YEAR) {
+ if (isSupported(INSTANT_SECONDS))
+ return zdt().toLocalDate().getMonthValue();
+ return 1;
+ }
+
+ return 0;
+ }
+
+ @Override /* TemporalAccessor */
+ public int get(TemporalField field) {
+ if (inner.isSupported(field))
+ return inner.get(field);
+ return (int)getLong(field);
+ }
+
+ private int iget(TemporalField field) {
+ return inner.get(field);
+ }
+
+ private ZonedDateTime zdt() {
+ if (zdt == null)
+ zdt = ZonedDateTime.from(this);
+ return zdt;
+ }
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalCalendarSwap.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalCalendarSwap.java
index 82afa6d..3b8b670 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalCalendarSwap.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalCalendarSwap.java
@@ -26,24 +26,6 @@
*
* <p>
* Uses the {@link DateTimeFormatter} class for converting {@link Calendar} objects.
- *
- * <p>
- * Serialization is relatively straightforward. The <c>Calendar</c> object is converted to a {@linked ZonedDateTime}.
- * Then the <c>ZonedDateTime</c> object is passed to the {@link DateTimeFormatter#format(TemporalAccessor)} method to produce
- * the string value.
- *
- * <p>
- * Parsing is a little more complicated. The <js>string</js> is parsed into an intermediate {@link Temporal} object before
- * being converted into a <c>Calendar</c>. The intermediate type can be any of the following:
- * <ul>
- * <li>{@link LocalDate} - For patterns containing dates without timezones.
- * <li>{@link LocalTime} - For patterns containing times without timezones.
- * <li>{@link LocalDateTime} - For patterns containing date-times without timezones.
- * <li>{@link ZonedDateTime} - For patterns containing date-times with timezones.
- * <li>{@link Instant} - For date-times with Zulu timezone.
- * <li>{@link OffsetDateTime} - For date-times with timezone offsets.
- * <li>{@link OffsetTime} - For times with timezone offsets.
- * </ul>
*/
public class TemporalCalendarSwap extends StringSwap<Calendar> {
@@ -55,7 +37,7 @@
public static class BasicIsoDate extends TemporalCalendarSwap {
/** Constructor.*/
public BasicIsoDate() {
- super("BASIC_ISO_DATE", LocalDate.class, true, false);
+ super("BASIC_ISO_DATE");
}
};
@@ -67,7 +49,7 @@
public static class IsoDate extends TemporalCalendarSwap {
/** Constructor.*/
public IsoDate() {
- super("ISO_DATE", LocalDate.class, false, true);
+ super("ISO_DATE");
}
};
@@ -79,7 +61,7 @@
public static class IsoDateTime extends TemporalCalendarSwap {
/** Constructor.*/
public IsoDateTime() {
- super("ISO_DATE_TIME", ZonedDateTime.class, false, false);
+ super("ISO_DATE_TIME");
}
};
@@ -91,7 +73,7 @@
public static class IsoInstant extends TemporalCalendarSwap {
/** Constructor.*/
public IsoInstant() {
- super("ISO_INSTANT", Instant.class, false, false);
+ super("ISO_INSTANT");
}
};
@@ -103,7 +85,7 @@
public static class IsoLocalDate extends TemporalCalendarSwap {
/** Constructor.*/
public IsoLocalDate() {
- super("ISO_LOCAL_DATE", LocalDate.class, false, false);
+ super("ISO_LOCAL_DATE");
}
};
@@ -115,7 +97,7 @@
public static class IsoLocalDateTime extends TemporalCalendarSwap {
/** Constructor.*/
public IsoLocalDateTime() {
- super("ISO_LOCAL_DATE_TIME", LocalDateTime.class, false, false);
+ super("ISO_LOCAL_DATE_TIME");
}
};
@@ -127,7 +109,7 @@
public static class IsoLocalTime extends TemporalCalendarSwap {
/** Constructor.*/
public IsoLocalTime() {
- super("ISO_LOCAL_TIME", LocalTime.class, false, false);
+ super("ISO_LOCAL_TIME");
}
};
@@ -139,7 +121,7 @@
public static class IsoOffsetDate extends TemporalCalendarSwap {
/** Constructor.*/
public IsoOffsetDate() {
- super("ISO_OFFSET_DATE", LocalDate.class, false, true);
+ super("ISO_OFFSET_DATE");
}
};
@@ -151,7 +133,7 @@
public static class IsoOffsetDateTime extends TemporalCalendarSwap {
/** Constructor.*/
public IsoOffsetDateTime() {
- super("ISO_OFFSET_DATE_TIME", OffsetDateTime.class, false, false);
+ super("ISO_OFFSET_DATE_TIME");
}
};
@@ -163,7 +145,7 @@
public static class IsoOffsetTime extends TemporalCalendarSwap {
/** Constructor.*/
public IsoOffsetTime() {
- super("ISO_OFFSET_TIME", OffsetTime.class, false, false);
+ super("ISO_OFFSET_TIME");
}
};
@@ -175,7 +157,7 @@
public static class IsoOrdinalDate extends TemporalCalendarSwap {
/** Constructor.*/
public IsoOrdinalDate() {
- super("ISO_ORDINAL_DATE", LocalDate.class, false, true);
+ super("ISO_ORDINAL_DATE");
}
};
@@ -187,7 +169,7 @@
public static class IsoTime extends TemporalCalendarSwap {
/** Constructor.*/
public IsoTime() {
- super("ISO_TIME", OffsetTime.class, false, false);
+ super("ISO_TIME");
}
};
@@ -199,7 +181,7 @@
public static class IsoWeekDate extends TemporalCalendarSwap {
/** Constructor.*/
public IsoWeekDate() {
- super("ISO_WEEK_DATE", LocalDate.class, false, true);
+ super("ISO_WEEK_DATE");
}
};
@@ -211,7 +193,7 @@
public static class IsoZonedDateTime extends TemporalCalendarSwap {
/** Constructor.*/
public IsoZonedDateTime() {
- super("ISO_ZONED_DATE_TIME", ZonedDateTime.class, false, false);
+ super("ISO_ZONED_DATE_TIME");
}
};
@@ -223,40 +205,21 @@
public static class Rfc1123DateTime extends TemporalCalendarSwap {
/** Constructor.*/
public Rfc1123DateTime() {
- super("RFC_1123_DATE_TIME", ZonedDateTime.class, false, false);
+ super("RFC_1123_DATE_TIME");
}
};
- private final TemporalParser<? extends Temporal> intermediateParser;
private final DateTimeFormatter formatter;
- private final boolean serializeWithoutTimezone, parseTimezoneSeparately;
/**
* Constructor.
*
* @param pattern The timestamp format or name of predefined {@link DateTimeFormatter}.
- * @param intermediateType The intermediate Java 8 data type to parse into before converting to a Calendar object.
- * @param serializeWithoutTimezone <jk>true</jk> if the date should be converted to local-date-time before serialization.
- * @param parseTimezoneSeparately <jk>true</jk> if the time zone should be persisted on parsing when {@link LocalDate} is the intermediate type.
*/
- public TemporalCalendarSwap(String pattern, Class<? extends Temporal> intermediateType, boolean serializeWithoutTimezone, boolean parseTimezoneSeparately) {
+ public TemporalCalendarSwap(String pattern) {
super(Calendar.class);
- this.intermediateParser = TemporalParserCache.getTemporalParser(intermediateType);
this.formatter = DateUtils.getFormatter(pattern);
- this.serializeWithoutTimezone = serializeWithoutTimezone;
- this.parseTimezoneSeparately = parseTimezoneSeparately;
- }
-
- /**
- * Converts the specified intermediate {@link Temporal} object to a {@link Calendar} object.
- *
- * @param bs The current bean session.
- * @param temporal The intermediate temporal object.
- * @return The converted date.
- */
- protected Calendar toCalendar(BeanSession bs, Temporal temporal) {
- return DateUtils.toCalendar(temporal, bs.getTimeZoneId());
}
@Override /* PojoSwap */
@@ -264,23 +227,16 @@
if (o == null)
return null;
ZonedDateTime t = o instanceof GregorianCalendar ? ((GregorianCalendar)o).toZonedDateTime() : o.toInstant().atZone(session.getTimeZoneId());
- return formatter.format(serializeWithoutTimezone ? t.toLocalDateTime() : t);
+ return formatter.format(t);
}
@Override /* PojoSwap */
public Calendar unswap(BeanSession session, String f, ClassMeta<?> hint) throws Exception {
if (f == null)
return null;
- Temporal t = intermediateParser.parse(f, formatter);
- if (parseTimezoneSeparately) {
- TemporalAccessor ta = formatter.parse(f);
- if (ta.query(TemporalQueries.zone()) != null) {
- ZoneId offset = ZoneId.from(ta);
- t = ((LocalDate)t).atStartOfDay(offset);
- }
- }
-
- return toCalendar(session, t);
+ ZoneId offset = session.getTimeZoneId();
+ TemporalAccessor ta = new DefaultingTemporalAccessor(formatter.parse(f), offset);
+ return GregorianCalendar.from(ZonedDateTime.from(ta));
}
}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalDateSwap.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalDateSwap.java
index d17cade..44696af 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalDateSwap.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalDateSwap.java
@@ -26,25 +26,6 @@
*
* <p>
* Uses the {@link DateTimeFormatter} class for converting {@link Date} objects.
- *
- * <p>
- * Serialization is relatively straightforward. The <c>Date</c> object is converted to a {@linked ZonedDateTime}
- * object using the time zone defined by the {@link BeanSession#getTimeZoneId()} method. Then the
- * <c>ZonedDateTime</c> object is passed to the {@link DateTimeFormatter#format(TemporalAccessor)} method to produce
- * the string value.
- *
- * <p>
- * Parsing is a little more complicated. The string is parsed into an intermediate {@link Temporal} object before
- * being converted into a <c>Date</c>. The intermediate type can be any of the following:
- * <ul>
- * <li>{@link LocalDate} - For patterns containing dates without timezones.
- * <li>{@link LocalTime} - For patterns containing times without timezones.
- * <li>{@link LocalDateTime} - For patterns containing date-times without timezones.
- * <li>{@link ZonedDateTime} - For patterns containing date-times with timezones.
- * <li>{@link Instant} - For date-times with Zulu timezone.
- * <li>{@link OffsetDateTime} - For date-times with timezone offsets.
- * <li>{@link OffsetTime} - For times with timezone offsets.
- * </ul>
*/
public class TemporalDateSwap extends StringSwap<Date> {
@@ -56,7 +37,7 @@
public static class BasicIsoDate extends TemporalDateSwap {
/** Constructor.*/
public BasicIsoDate() {
- super("BASIC_ISO_DATE", LocalDate.class, true);
+ super("BASIC_ISO_DATE");
}
};
@@ -68,7 +49,7 @@
public static class IsoDate extends TemporalDateSwap {
/** Constructor.*/
public IsoDate() {
- super("ISO_DATE", LocalDate.class, false);
+ super("ISO_DATE");
}
};
@@ -80,7 +61,7 @@
public static class IsoDateTime extends TemporalDateSwap {
/** Constructor.*/
public IsoDateTime() {
- super("ISO_DATE_TIME", ZonedDateTime.class, false);
+ super("ISO_DATE_TIME");
}
};
@@ -92,7 +73,7 @@
public static class IsoInstant extends TemporalDateSwap {
/** Constructor.*/
public IsoInstant() {
- super("ISO_INSTANT", Instant.class, false);
+ super("ISO_INSTANT");
}
};
@@ -104,7 +85,7 @@
public static class IsoLocalDate extends TemporalDateSwap {
/** Constructor.*/
public IsoLocalDate() {
- super("ISO_LOCAL_DATE", LocalDate.class, false);
+ super("ISO_LOCAL_DATE");
}
};
@@ -116,7 +97,7 @@
public static class IsoLocalDateTime extends TemporalDateSwap {
/** Constructor.*/
public IsoLocalDateTime() {
- super("ISO_LOCAL_DATE_TIME", LocalDateTime.class, false);
+ super("ISO_LOCAL_DATE_TIME");
}
};
@@ -128,7 +109,7 @@
public static class IsoLocalTime extends TemporalDateSwap {
/** Constructor.*/
public IsoLocalTime() {
- super("ISO_LOCAL_TIME", LocalTime.class, false);
+ super("ISO_LOCAL_TIME");
}
};
@@ -140,7 +121,7 @@
public static class IsoOffsetDate extends TemporalDateSwap {
/** Constructor.*/
public IsoOffsetDate() {
- super("ISO_OFFSET_DATE", LocalDate.class, false);
+ super("ISO_OFFSET_DATE");
}
};
@@ -152,7 +133,7 @@
public static class IsoOffsetDateTime extends TemporalDateSwap {
/** Constructor.*/
public IsoOffsetDateTime() {
- super("ISO_OFFSET_DATE_TIME", OffsetDateTime.class, false);
+ super("ISO_OFFSET_DATE_TIME");
}
};
@@ -164,7 +145,7 @@
public static class IsoOffsetTime extends TemporalDateSwap {
/** Constructor.*/
public IsoOffsetTime() {
- super("ISO_OFFSET_TIME", OffsetTime.class, false);
+ super("ISO_OFFSET_TIME");
}
};
@@ -176,7 +157,7 @@
public static class IsoOrdinalDate extends TemporalDateSwap {
/** Constructor.*/
public IsoOrdinalDate() {
- super("ISO_ORDINAL_DATE", LocalDate.class, false);
+ super("ISO_ORDINAL_DATE");
}
};
@@ -188,7 +169,7 @@
public static class IsoTime extends TemporalDateSwap {
/** Constructor.*/
public IsoTime() {
- super("ISO_TIME", OffsetTime.class, false);
+ super("ISO_TIME");
}
};
@@ -200,7 +181,7 @@
public static class IsoWeekDate extends TemporalDateSwap {
/** Constructor.*/
public IsoWeekDate() {
- super("ISO_WEEK_DATE", LocalDate.class, false);
+ super("ISO_WEEK_DATE");
}
};
@@ -212,7 +193,7 @@
public static class IsoZonedDateTime extends TemporalDateSwap {
/** Constructor.*/
public IsoZonedDateTime() {
- super("ISO_ZONED_DATE_TIME", ZonedDateTime.class, false);
+ super("ISO_ZONED_DATE_TIME");
}
};
@@ -224,53 +205,36 @@
public static class Rfc1123DateTime extends TemporalDateSwap {
/** Constructor.*/
public Rfc1123DateTime() {
- super("RFC_1123_DATE_TIME", ZonedDateTime.class, false);
+ super("RFC_1123_DATE_TIME");
}
};
- private final TemporalParser<? extends Temporal> intermediateParser;
private final DateTimeFormatter formatter;
- private final boolean serializeWithoutTimezone;
/**
* Constructor.
*
* @param pattern The timestamp format or name of predefined {@link DateTimeFormatter}.
- * @param intermediateType The intermediate Java 8 data type to parse into before converting to a Date object.
- * @param serializeWithoutTimezone <jk>true</jk> if the date should be converted to local-date-time before serialization.
*/
- public TemporalDateSwap(String pattern, Class<? extends Temporal> intermediateType, boolean serializeWithoutTimezone) {
+ public TemporalDateSwap(String pattern) {
super(Date.class);
- this.intermediateParser = TemporalParserCache.getTemporalParser(intermediateType);
this.formatter = DateUtils.getFormatter(pattern);
- this.serializeWithoutTimezone = serializeWithoutTimezone;
- }
-
- /**
- * Converts the specified intermediate {@link Temporal} object to a {@link Date} object.
- *
- * @param bs The current bean session.
- * @param temporal The intermediate temporal object.
- * @return The converted date.
- */
- protected Date toDate(BeanSession bs, Temporal temporal) {
- return DateUtils.toDate(temporal, bs.getTimeZoneId());
}
@Override /* PojoSwap */
public String swap(BeanSession session, Date o) throws Exception {
if (o == null)
return null;
- ZonedDateTime t = o.toInstant().atZone(session.getTimeZoneId());
- return formatter.format(serializeWithoutTimezone ? t.toLocalDateTime() : t);
+ return formatter.format(o.toInstant().atZone(session.getTimeZoneId()));
}
@Override /* PojoSwap */
public Date unswap(BeanSession session, String f, ClassMeta<?> hint) throws Exception {
if (f == null)
return null;
- Temporal t = intermediateParser.parse(f, formatter);
- return toDate(session, t);
+ ZoneId offset = session.getTimeZoneId();
+ TemporalAccessor ta = new DefaultingTemporalAccessor(formatter.parse(f), offset);
+ return Date.from(ZonedDateTime.from(ta).toInstant());
}
}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalParser.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalParser.java
deleted file mode 100644
index a22bf0a..0000000
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalParser.java
+++ /dev/null
@@ -1,70 +0,0 @@
-// ***************************************************************************************************************************
-// * 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.juneau.transforms;
-
-import java.lang.reflect.*;
-import java.time.format.*;
-import java.time.temporal.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.reflect.*;
-
-/**
- * A helper class for converting strings to {@link Temporal} objects.
- *
- * <p>
- * Looks for static <cb>from()</cb> or <cb>parse()</cb> methods to use on the temporal class to instantiate instances.
- *
- * @param <T> The temporal class type.
- */
-class TemporalParser<T extends Temporal> {
-
- private final Method fromMethod;
- private final Method parseMethod;
- private final ClassInfo ci;
-
- /**
- * Constructor.
- *
- * @param c The temporal class type.
- */
- public TemporalParser(Class<T> c) {
- this.ci = ClassInfo.of(c);
- this.fromMethod = ci.getStaticPublicMethodInner("from", c, TemporalAccessor.class);
- this.parseMethod = ci.getStaticPublicMethodInner("parse", c, String.class, DateTimeFormatter.class);
- }
-
- /**
- * Parses the specified input using the specified formatter.
- *
- * @param input The input string.
- * @param formatter The formatter.
- * @return The parsed string.
- * @throws ExecutableException If input could not be parsed using the specified formatter.
- */
- @SuppressWarnings("unchecked")
- public T parse(String input, DateTimeFormatter formatter) throws ExecutableException {
- try {
- if (parseMethod != null) {
- return (T)parseMethod.invoke(null, input, formatter);
- }
- if (fromMethod != null) {
- TemporalAccessor ta = formatter.parse(input);
- return (T)fromMethod.invoke(null, ta);
- }
- throw new ExecutableException("From or Parse methods not found on temporal class ''{0}''", ci.getSimpleName());
- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
- throw new ExecutableException(e);
- }
- }
-}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalParserCache.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalParserCache.java
deleted file mode 100644
index 5a61933..0000000
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalParserCache.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// ***************************************************************************************************************************
-// * 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.juneau.transforms;
-
-import java.time.temporal.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-/**
- * Cache of reusable <c>TemporalParser</c> objects.
- */
-class TemporalParserCache {
-
- private static final Map<Class<? extends Temporal>,TemporalParser<? extends Temporal>> TO_TEMPORAL_CACHE = new ConcurrentHashMap<>();
-
- /**
- * Retrieves a temporal parser for the specified {@link Temporal} class.
- *
- * @param <T> The temporal class.
- * @param c The temporal class.
- * @return The parser for the specified class.
- */
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public static <T extends Temporal> TemporalParser<T> getTemporalParser(Class<T> c) {
- TemporalParser tt = TO_TEMPORAL_CACHE.get(c);
- if (tt == null) {
- tt = new TemporalParser(c);
- TO_TEMPORAL_CACHE.put(c, tt);
- }
- return tt;
- }
-}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalSwap.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalSwap.java
index 5f54421..ff3fb42 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalSwap.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transforms/TemporalSwap.java
@@ -12,16 +12,18 @@
// ***************************************************************************************************************************
package org.apache.juneau.transforms;
+import java.lang.reflect.*;
import java.time.*;
import java.time.chrono.*;
import java.time.format.*;
import java.time.temporal.*;
import java.util.*;
+import java.util.concurrent.*;
import org.apache.juneau.*;
import org.apache.juneau.internal.*;
+import org.apache.juneau.reflect.*;
import org.apache.juneau.transform.*;
-import org.apache.juneau.utils.*;
/**
* Swap that converts {@link Temporal} objects to strings.
@@ -57,14 +59,7 @@
public static class BasicIsoDate extends TemporalSwap {
/** Constructor.*/
public BasicIsoDate() {
- super(
- "BASIC_ISO_DATE",
- LocalDate.class,
- ASet.create(LocalDate.class, LocalDateTime.class),
- LocalDate.class,
- ASet.create(LocalDate.class, Year.class, YearMonth.class),
- false
- );
+ super("BASIC_ISO_DATE", true);
}
}
@@ -76,14 +71,7 @@
public static class IsoDate extends TemporalSwap {
/** Constructor.*/
public IsoDate() {
- super(
- "ISO_DATE",
- LocalDate.class,
- ASet.create(LocalDate.class, LocalDateTime.class, OffsetDateTime.class, ZonedDateTime.class),
- LocalDate.class,
- ASet.create(LocalDate.class),
- true
- );
+ super("ISO_DATE", true);
}
}
@@ -95,14 +83,7 @@
public static class IsoDateTime extends TemporalSwap {
/** Constructor.*/
public IsoDateTime() {
- super(
- "ISO_DATE_TIME",
- ZonedDateTime.class,
- ASet.create(OffsetDateTime.class, ZonedDateTime.class),
- ZonedDateTime.class,
- ASet.create(Instant.class, LocalDate.class, LocalDateTime.class, LocalTime.class, OffsetDateTime.class, OffsetTime.class, Year.class, YearMonth.class, ZonedDateTime.class),
- false
- );
+ super("ISO_DATE_TIME", true);
}
}
@@ -114,14 +95,7 @@
public static class IsoInstant extends TemporalSwap {
/** Constructor.*/
public IsoInstant() {
- super(
- "ISO_INSTANT",
- Instant.class,
- ASet.create(Instant.class, OffsetDateTime.class, ZonedDateTime.class),
- Instant.class,
- ASet.create(Instant.class),
- false
- );
+ super("ISO_INSTANT", false);
}
}
@@ -133,14 +107,7 @@
public static class IsoLocalDate extends TemporalSwap {
/** Constructor.*/
public IsoLocalDate() {
- super(
- "ISO_LOCAL_DATE",
- LocalDate.class,
- ASet.create(LocalDate.class, LocalDateTime.class, OffsetDateTime.class, ZonedDateTime.class),
- LocalDate.class,
- ASet.create(LocalDate.class, Year.class, YearMonth.class),
- false
- );
+ super("ISO_LOCAL_DATE", false);
}
}
@@ -152,14 +119,7 @@
public static class IsoLocalDateTime extends TemporalSwap {
/** Constructor.*/
public IsoLocalDateTime() {
- super(
- "ISO_LOCAL_DATE_TIME",
- LocalDateTime.class,
- ASet.create(LocalDateTime.class, OffsetDateTime.class, ZonedDateTime.class),
- LocalDateTime.class,
- ASet.create(LocalDate.class, LocalDateTime.class, LocalTime.class, Year.class, YearMonth.class),
- false
- );
+ super("ISO_LOCAL_DATE_TIME", true);
}
}
@@ -171,14 +131,7 @@
public static class IsoLocalTime extends TemporalSwap {
/** Constructor.*/
public IsoLocalTime() {
- super(
- "ISO_LOCAL_TIME",
- LocalTime.class,
- ASet.create(LocalDateTime.class, LocalTime.class, OffsetDateTime.class, OffsetTime.class, ZonedDateTime.class),
- LocalTime.class,
- ASet.create(LocalTime.class),
- false
- );
+ super("ISO_LOCAL_TIME", true);
}
}
@@ -190,14 +143,7 @@
public static class IsoOffsetDate extends TemporalSwap {
/** Constructor.*/
public IsoOffsetDate() {
- super(
- "ISO_OFFSET_DATE",
- ZonedDateTime.class,
- ASet.create(OffsetDateTime.class, ZonedDateTime.class),
- LocalDate.class,
- ASet.create(LocalDate.class, Year.class, YearMonth.class),
- true
- );
+ super("ISO_OFFSET_DATE", false);
}
}
@@ -209,14 +155,7 @@
public static class IsoOffsetDateTime extends TemporalSwap {
/** Constructor.*/
public IsoOffsetDateTime() {
- super(
- "ISO_OFFSET_DATE_TIME",
- OffsetDateTime.class,
- ASet.create(OffsetDateTime.class, ZonedDateTime.class),
- OffsetDateTime.class,
- ASet.create(Instant.class, LocalDate.class, LocalDateTime.class, LocalTime.class, OffsetDateTime.class, OffsetTime.class, Year.class, YearMonth.class, ZonedDateTime.class),
- false
- );
+ super("ISO_OFFSET_DATE_TIME", false);
}
}
@@ -228,14 +167,7 @@
public static class IsoOffsetTime extends TemporalSwap {
/** Constructor.*/
public IsoOffsetTime() {
- super(
- "ISO_OFFSET_TIME",
- OffsetTime.class,
- ASet.create(OffsetDateTime.class, OffsetTime.class, ZonedDateTime.class),
- OffsetTime.class,
- ASet.create(LocalTime.class, OffsetTime.class),
- false
- );
+ super("ISO_OFFSET_TIME", false);
}
}
@@ -247,14 +179,7 @@
public static class IsoOrdinalDate extends TemporalSwap {
/** Constructor.*/
public IsoOrdinalDate() {
- super(
- "ISO_ORDINAL_DATE",
- LocalDate.class,
- ASet.create(LocalDate.class, LocalDateTime.class, OffsetDateTime.class, ZonedDateTime.class),
- LocalDate.class,
- ASet.create(LocalDate.class, Year.class, YearMonth.class),
- true
- );
+ super("ISO_ORDINAL_DATE", true);
}
}
@@ -266,14 +191,7 @@
public static class IsoTime extends TemporalSwap {
/** Constructor.*/
public IsoTime() {
- super(
- "ISO_TIME",
- OffsetTime.class,
- ASet.create(LocalTime.class, OffsetDateTime.class, OffsetTime.class, ZonedDateTime.class),
- OffsetTime.class,
- ASet.create(LocalTime.class, OffsetTime.class),
- false
- );
+ super("ISO_TIME", true);
}
}
@@ -285,14 +203,7 @@
public static class IsoWeekDate extends TemporalSwap {
/** Constructor.*/
public IsoWeekDate() {
- super(
- "ISO_WEEK_DATE",
- LocalDate.class,
- ASet.create(LocalDate.class, LocalDateTime.class, OffsetDateTime.class, ZonedDateTime.class),
- LocalDate.class,
- ASet.create(LocalDate.class, Year.class, YearMonth.class),
- true
- );
+ super("ISO_WEEK_DATE", true);
}
}
@@ -304,14 +215,7 @@
public static class IsoYear extends TemporalSwap {
/** Constructor.*/
public IsoYear() {
- super(
- "uuuu",
- Year.class,
- ASet.create(LocalDate.class, LocalDateTime.class, OffsetDateTime.class, Year.class, YearMonth.class, ZonedDateTime.class),
- Year.class,
- ASet.create(Year.class),
- false
- );
+ super("uuuu", true);
}
}
@@ -323,14 +227,7 @@
public static class IsoYearMonth extends TemporalSwap {
/** Constructor.*/
public IsoYearMonth() {
- super(
- "uuuu-MM",
- YearMonth.class,
- ASet.create(LocalDate.class, LocalDateTime.class, OffsetDateTime.class, YearMonth.class, ZonedDateTime.class),
- YearMonth.class,
- ASet.create(Year.class, YearMonth.class),
- false
- );
+ super("uuuu-MM", true);
}
}
@@ -342,14 +239,7 @@
public static class IsoZonedDateTime extends TemporalSwap {
/** Constructor.*/
public IsoZonedDateTime() {
- super(
- "ISO_ZONED_DATE_TIME",
- ZonedDateTime.class,
- ASet.create(LocalDate.class, OffsetDateTime.class, ZonedDateTime.class),
- ZonedDateTime.class,
- ASet.create(Instant.class, LocalDate.class, LocalDateTime.class, LocalTime.class, OffsetDateTime.class, OffsetTime.class, Year.class, YearMonth.class, ZonedDateTime.class),
- false
- );
+ super("ISO_ZONED_DATE_TIME", false);
}
}
@@ -361,52 +251,90 @@
public static class Rfc1123DateTime extends TemporalSwap {
/** Constructor.*/
public Rfc1123DateTime() {
- super(
- "RFC_1123_DATE_TIME",
- ZonedDateTime.class,
- ASet.create(OffsetDateTime.class, ZonedDateTime.class),
- ZonedDateTime.class,
- ASet.create(Instant.class, LocalDate.class, LocalDateTime.class, LocalTime.class, OffsetDateTime.class, OffsetTime.class, Year.class, YearMonth.class, ZonedDateTime.class),
- false
- );
+ super("RFC_1123_DATE_TIME", false);
}
}
+ private static final ZoneId Z = ZoneId.of("Z");
+ private static final Map<Class<? extends Temporal>,Method> FROM_METHODS = new ConcurrentHashMap<>();
- private final TemporalParser<? extends Temporal> intermediateParser;
- private final Class<? extends Temporal> intermediateSerializeType;
+ private static Method findParseMethod(Class<? extends Temporal> c) throws ExecutableException {
+ Method m = FROM_METHODS.get(c);
+ if (m == null) {
+ m = ClassInfo.of(c).getStaticPublicMethodInner("from", c, TemporalAccessor.class);
+ if (m == null)
+ throw new ExecutableException("Parse method not found on temporal class ''{0}''", c.getSimpleName());
+ FROM_METHODS.put(c, m);
+ }
+ return m;
+ }
+
private final DateTimeFormatter formatter;
- private final Set<Class<? extends Temporal>> directSerializeClasses, directParseClasses;
- private final boolean parseTimezoneSeparately;
+ private final boolean zoneOptional;
/**
* Constructor.
*
* @param pattern The timestamp format or name of predefined {@link DateTimeFormatter}.
- * @param intermediateSerializeType The intermediate Java 8 data type to convert to before serializing.
- * @param directSerializeClasses Classes that can be serialized directly into without having to go through the intermediate type.
- * @param intermediateParseType The intermediate Java 8 data type to parse into before converting to a Date object.
- * @param directParseClasses Classes that can be parsed directly into without having to go through the intermediate type.
- * @param parseTimezoneSeparately <jk>true</jk> if the time zone should be persisted on parsing when {@link LocalDate} is the intermediate type.
+ * @param zoneOptional <jk>true</jk> if the time zone on the pattern is optional.
*/
- public TemporalSwap(String pattern, Class<? extends Temporal> intermediateSerializeType, Set<Class<? extends Temporal>> directSerializeClasses, Class<? extends Temporal> intermediateParseType, Set<Class<? extends Temporal>> directParseClasses, boolean parseTimezoneSeparately) {
+ public TemporalSwap(String pattern, boolean zoneOptional) {
super(Temporal.class);
- this.intermediateParser = TemporalParserCache.getTemporalParser(intermediateParseType);
this.formatter = DateUtils.getFormatter(pattern);
- this.directSerializeClasses = directSerializeClasses == null ? Collections.emptySet() : directSerializeClasses;
- this.directParseClasses = directParseClasses == null ? Collections.emptySet() : directParseClasses;
- this.intermediateSerializeType = intermediateSerializeType;
- this.parseTimezoneSeparately = parseTimezoneSeparately;
+ this.zoneOptional = zoneOptional;
+ }
+
+ /**
+ * Returns <jk>true</jk> if the time zone on the pattern is optional.
+ *
+ * <p>
+ * If it's not optional, then local dates/times must be converted into zoned times using the session time zone.
+ * Otherwise, local date/times are fine.
+ *
+ * @return <jk>true</jk> if the time zone on the pattern is optional.
+ */
+ protected boolean zoneOptional() {
+ return zoneOptional;
}
@Override /* PojoSwap */
public String swap(BeanSession session, Temporal o) throws Exception {
if (o == null)
return null;
- if (directSerializeClasses.contains(o.getClass()))
- return formatter.format(o);
- Temporal o2 = DateUtils.toTemporal(o, intermediateSerializeType, session.getTimeZoneId());
- return formatter.format(o2);
+ o = convertToSerializable(session, o);
+ return formatter.format(o);
+ }
+
+ /**
+ * Converts the specified temporal object to a form suitable to be serialized using any pattern.
+ *
+ * @param session The current bean session.
+ * @param t The temporal object to convert.
+ * @return The converted temporal object.
+ */
+ protected Temporal convertToSerializable(BeanSession session, Temporal t) {
+
+ ZoneId zoneId = session.getTimeZoneId();
+ Class<? extends Temporal> tc = t.getClass();
+
+ // Instant is always serialized in GMT.
+ if (tc == Instant.class)
+ return ZonedDateTime.from(defaulting(t, Z));
+
+ // These can handle any pattern.
+ if (tc == ZonedDateTime.class || tc == OffsetDateTime.class)
+ return t;
+
+ // Pattern optionally includes a time zone, so zoned and local date-times are good.
+ if (zoneOptional()) {
+ if (tc == LocalDateTime.class)
+ return t;
+ if (tc == OffsetTime.class)
+ return ZonedDateTime.from(defaulting(t, zoneId));
+ return LocalDateTime.from(defaulting(t, zoneId));
+ }
+
+ return ZonedDateTime.from(defaulting(t, zoneId));
}
@SuppressWarnings("unchecked")
@@ -414,22 +342,20 @@
public Temporal unswap(BeanSession session, String f, ClassMeta<?> hint) throws Exception {
if (hint == null)
hint = session.getClassMeta(Instant.class);
-
Class<? extends Temporal> tc = (Class<? extends Temporal>)hint.getInnerClass();
- if (directParseClasses.contains(tc))
- return TemporalParserCache.getTemporalParser(tc).parse(f, formatter);
+ ZoneId offset = session.getTimeZoneId();
- Temporal t = intermediateParser.parse(f, formatter);
+ if (tc == Instant.class)
+ offset = Z;
- if (parseTimezoneSeparately) {
- TemporalAccessor ta = formatter.parse(f);
- if (ta.query(TemporalQueries.zone()) != null) {
- ZoneId offset = ZoneId.from(ta);
- t = ((LocalDate)t).atStartOfDay(offset);
- }
- }
+ Method parseMethod = findParseMethod(tc);
- return DateUtils.toTemporal(t, tc, session.getTimeZoneId());
+ TemporalAccessor ta = defaulting(formatter.parse(f), offset);
+ return (Temporal)parseMethod.invoke(null, ta);
+ }
+
+ private final TemporalAccessor defaulting(TemporalAccessor t, ZoneId zoneId) {
+ return new DefaultingTemporalAccessor(t, zoneId);
}
}