36
36
import java .lang .reflect .TypeVariable ;
37
37
import java .lang .reflect .WildcardType ;
38
38
import java .math .BigDecimal ;
39
+ import java .time .Instant ;
39
40
import java .util .ArrayList ;
40
41
import java .util .Collection ;
41
42
import java .util .Collections ;
@@ -175,6 +176,9 @@ private static <T> Object serialize(T o, ErrorPath path) {
175
176
|| o instanceof FieldValue
176
177
|| o instanceof Value ) {
177
178
return o ;
179
+ } else if (o instanceof Instant ) {
180
+ Instant instant = (Instant ) o ;
181
+ return Timestamp .ofTimeSecondsAndNanos (instant .getEpochSecond (), instant .getNano ());
178
182
} else {
179
183
Class <T > clazz = (Class <T >) o .getClass ();
180
184
BeanMapper <T > mapper = loadOrCreateBeanMapperForClass (clazz );
@@ -233,6 +237,8 @@ private static <T> T deserializeToClass(Object o, Class<T> clazz, DeserializeCon
233
237
return (T ) convertDate (o , context );
234
238
} else if (Timestamp .class .isAssignableFrom (clazz )) {
235
239
return (T ) convertTimestamp (o , context );
240
+ } else if (Instant .class .isAssignableFrom (clazz )) {
241
+ return (T ) convertInstant (o , context );
236
242
} else if (Blob .class .isAssignableFrom (clazz )) {
237
243
return (T ) convertBlob (o , context );
238
244
} else if (GeoPoint .class .isAssignableFrom (clazz )) {
@@ -557,6 +563,19 @@ private static Timestamp convertTimestamp(Object o, DeserializeContext context)
557
563
}
558
564
}
559
565
566
+ private static Instant convertInstant (Object o , DeserializeContext context ) {
567
+ if (o instanceof Timestamp ) {
568
+ Timestamp timestamp = (Timestamp ) o ;
569
+ return Instant .ofEpochSecond (timestamp .getSeconds (), timestamp .getNanos ());
570
+ } else if (o instanceof Date ) {
571
+ return Instant .ofEpochMilli (((Date ) o ).getTime ());
572
+ } else {
573
+ throw deserializeError (
574
+ context .errorPath ,
575
+ "Failed to convert value of type " + o .getClass ().getName () + " to Instant" );
576
+ }
577
+ }
578
+
560
579
private static Blob convertBlob (Object o , DeserializeContext context ) {
561
580
if (o instanceof Blob ) {
562
581
return (Blob ) o ;
@@ -976,13 +995,13 @@ Map<String, Object> serialize(T object, ErrorPath path) {
976
995
private void applyFieldAnnotations (Field field ) {
977
996
if (field .isAnnotationPresent (ServerTimestamp .class )) {
978
997
Class <?> fieldType = field .getType ();
979
- if (fieldType != Date .class && fieldType != Timestamp .class ) {
998
+ if (fieldType != Date .class && fieldType != Timestamp .class && fieldType != Instant . class ) {
980
999
throw new IllegalArgumentException (
981
1000
"Field "
982
1001
+ field .getName ()
983
1002
+ " is annotated with @ServerTimestamp but is "
984
1003
+ fieldType
985
- + " instead of Date or Timestamp ." );
1004
+ + " instead of Date, Timestamp, or Instant ." );
986
1005
}
987
1006
serverTimestamps .add (propertyName (field ));
988
1007
}
@@ -997,13 +1016,15 @@ private void applyFieldAnnotations(Field field) {
997
1016
private void applyGetterAnnotations (Method method ) {
998
1017
if (method .isAnnotationPresent (ServerTimestamp .class )) {
999
1018
Class <?> returnType = method .getReturnType ();
1000
- if (returnType != Date .class && returnType != Timestamp .class ) {
1019
+ if (returnType != Date .class
1020
+ && returnType != Timestamp .class
1021
+ && returnType != Instant .class ) {
1001
1022
throw new IllegalArgumentException (
1002
1023
"Method "
1003
1024
+ method .getName ()
1004
1025
+ " is annotated with @ServerTimestamp but returns "
1005
1026
+ returnType
1006
- + " instead of Date or Timestamp ." );
1027
+ + " instead of Date, Timestamp, or Instant ." );
1007
1028
}
1008
1029
serverTimestamps .add (propertyName (method ));
1009
1030
}
0 commit comments