1818import static com .google .firebase .firestore .util .ApiUtil .newInstance ;
1919
2020import android .net .Uri ;
21+ import android .os .Build ;
22+ import androidx .annotation .RequiresApi ;
2123import com .google .firebase .Timestamp ;
2224import com .google .firebase .firestore .Blob ;
2325import com .google .firebase .firestore .DocumentId ;
4244import java .lang .reflect .WildcardType ;
4345import java .net .URI ;
4446import java .net .URL ;
47+ import java .time .Instant ;
4548import java .util .ArrayList ;
4649import java .util .Collection ;
4750import java .util .Collections ;
@@ -177,6 +180,9 @@ private static <T> Object serialize(T o, ErrorPath path) {
177180 || o instanceof FieldValue
178181 || o instanceof VectorValue ) {
179182 return o ;
183+ } else if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O && o instanceof Instant ) {
184+ Instant instant = (Instant ) o ;
185+ return new Timestamp (instant .getEpochSecond (), instant .getNano ());
180186 } else if (o instanceof Uri || o instanceof URI || o instanceof URL ) {
181187 return o .toString ();
182188 } else {
@@ -237,6 +243,9 @@ private static <T> T deserializeToClass(Object o, Class<T> clazz, DeserializeCon
237243 return (T ) convertDate (o , context );
238244 } else if (Timestamp .class .isAssignableFrom (clazz )) {
239245 return (T ) convertTimestamp (o , context );
246+ } else if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O
247+ && Instant .class .isAssignableFrom (clazz )) {
248+ return (T ) convertInstant (o , context );
240249 } else if (Blob .class .isAssignableFrom (clazz )) {
241250 return (T ) convertBlob (o , context );
242251 } else if (GeoPoint .class .isAssignableFrom (clazz )) {
@@ -512,6 +521,20 @@ private static Timestamp convertTimestamp(Object o, DeserializeContext context)
512521 }
513522 }
514523
524+ @ RequiresApi (api = Build .VERSION_CODES .O )
525+ private static Instant convertInstant (Object o , DeserializeContext context ) {
526+ if (o instanceof Timestamp ) {
527+ Timestamp timestamp = (Timestamp ) o ;
528+ return Instant .ofEpochSecond (timestamp .getSeconds (), timestamp .getNanoseconds ());
529+ } else if (o instanceof Date ) {
530+ return Instant .ofEpochMilli (((Date ) o ).getTime ());
531+ } else {
532+ throw deserializeError (
533+ context .errorPath ,
534+ "Failed to convert value of type " + o .getClass ().getName () + " to Instant" );
535+ }
536+ }
537+
515538 private static Blob convertBlob (Object o , DeserializeContext context ) {
516539 if (o instanceof Blob ) {
517540 return (Blob ) o ;
@@ -933,13 +956,15 @@ Map<String, Object> serialize(T object, ErrorPath path) {
933956 private void applyFieldAnnotations (Field field ) {
934957 if (field .isAnnotationPresent (ServerTimestamp .class )) {
935958 Class <?> fieldType = field .getType ();
936- if (fieldType != Date .class && fieldType != Timestamp .class ) {
959+ if (fieldType != Date .class
960+ && fieldType != Timestamp .class
961+ && !(Build .VERSION .SDK_INT >= Build .VERSION_CODES .O && fieldType == Instant .class )) {
937962 throw new IllegalArgumentException (
938963 "Field "
939964 + field .getName ()
940965 + " is annotated with @ServerTimestamp but is "
941966 + fieldType
942- + " instead of Date or Timestamp ." );
967+ + " instead of Date, Timestamp, or Instant ." );
943968 }
944969 serverTimestamps .add (propertyName (field ));
945970 }
@@ -954,13 +979,15 @@ private void applyFieldAnnotations(Field field) {
954979 private void applyGetterAnnotations (Method method ) {
955980 if (method .isAnnotationPresent (ServerTimestamp .class )) {
956981 Class <?> returnType = method .getReturnType ();
957- if (returnType != Date .class && returnType != Timestamp .class ) {
982+ if (returnType != Date .class
983+ && returnType != Timestamp .class
984+ && !(Build .VERSION .SDK_INT >= Build .VERSION_CODES .O && returnType == Instant .class )) {
958985 throw new IllegalArgumentException (
959986 "Method "
960987 + method .getName ()
961988 + " is annotated with @ServerTimestamp but returns "
962989 + returnType
963- + " instead of Date or Timestamp ." );
990+ + " instead of Date, Timestamp, or Instant ." );
964991 }
965992 serverTimestamps .add (propertyName (method ));
966993 }
0 commit comments