【问题标题】:How to save Timestamp value in Cloud Firestore and perform query on it?如何在 Cloud Firestore 中保存时间戳值并对其执行查询?
【发布时间】:2020-07-02 20:50:12
【问题描述】:

我已经关注了这个Stackoverflow post,并且如果我们使用 ServerTimestamp 注释,则清楚地说明了如何存储时间戳。但是,我想询问其他替代方案,这些替代方案以后也可用于对它们执行查询。

关于不同的时间库(Java 8 之前/之后),我们可以将时间戳作为long 变量或ZonedDateTime 对象获取。我的问题是:

我们是否可以将ZonedDateTime 对象或long 变量保存为字符串,然后对其执行查询,或者我们必须在任何情况下使用ServerTimestamp 注释?

【问题讨论】:

    标签: android firebase google-cloud-firestore


    【解决方案1】:

    如果您要编写时间戳字段,并且不能使用服务器时间戳,则需要提供常规 Java Date 对象或 Firebase Timestamp 对象。这两种类型的值都将转换为文档中的时间戳字段。

    当您查询文档时,该字段将始终作为时间戳类型对象显示在文档快照中。

    【讨论】:

    • 好的。那么只有这两个被 Firebase 接受? (我之所以问,是因为文章说要避免使用 Date、SimpleDateType 之类的对象,或者我可能误解了它)
    • 只是日期和时间戳。您将不得不转换为其中之一。我建议尝试一下。
    • 谢谢!我会的!
    • @H.Karatsanov 虽然java.sql.Timestamp 是一个设计不佳且早已过时的类(在已经设计不佳的java.util.Date 之上的真正破解),但firebase Timestamp 类是更新的。我不知道,但我希望它不会具有 java.sql 类型的坏特性。
    • @OleV.V.你是对的。但由于 Firebase 仅适用于 Date,我们需要获取 LocalDateTime(ThreeTen.., java.time),然后将其解析为 Date,以便 Firebase 接受它。后面我会用代码来写答案
    【解决方案2】:

    我想通了。如您所知,当我们在 Android 中处理 Time 时,我们需要注意不同的 API,即 API 26 之前和之后的 API。 Stackoverflow 中有很多关于这个主题的文章,但概括地说,在 Android 8 (Oreo, API 26) 之前我们需要使用库 ThreeTenABP 而在 Android 8 之后我们需要使用 java.time

    实现如下所示:

    private Date getCurrentDate(){
            if(Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O){
                return Date.from(Instant.now());
            } else {
                AndroidThreeTen.init(this);
                return DateTimeUtils.toDate(org.threeten.bp.Instant.now());
            }
        }
    

    当然,你可以使用LocalDateTimeZonedDateTime等。

    Firebase 需要 Date 对象,或者您可以使用 @ServerTimestamp 注释并且在模型的构造函数中不提供任何参数。然后,Firebase 将在收到保存数据的请求时创建时间戳。像这样

    //When you provide Date 
    class SomeClass {
       private String someAttribute;
       private Date someDate;
       ...
       public SomeClass(String someAttribute, Date someDate, ...){
         this.someAttribute = someAttribute;
         this.someDate = someDate;
    
       }
    }
    
    //When you don't provide Date 
    class SomeClass {
       private String someAttribute;
       private @ServerTimestamp Date someDate;
       ...
       public SomeClass(String someAttribute, ...){
         this.someAttribute = someAttribute;
        ...
       }
    }
    
    

    (在开始活动时可能需要 Date 对象,但即使在 2-3 小时后也可能会向服务器发出请求。这就是为什么 @ServerTimestamp 对我来说效率低下。)

    检索以相同的方式发生。创建一个模型类,或使用HashMap(您的选择),但类型必须是Date。它根据日期和时间(时区,时间甚至高达微秒等)保存几乎所有类型的信息。

    大多数时候,用户只想查看小时:分钟形式的日期和时间。 您可以使用DateTimeFormatter 并提供您想要的模式(有很多标准)。就我而言,我以这种方式使用它:

    private String formatDate(Date date){
            if(Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O){
                java.time.LocalDateTime ldt = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
                java.time.format.DateTimeFormatter dtf = java.time.format.DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm");
                return ldt.format(dtf);
            } else {
                LocalDateTime ldt = Instant.ofEpochMilli(date.getTime()).atZone(org.threeten.bp.ZoneId.systemDefault()).toLocalDateTime();
                DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm");
                return ldt.format(dtf);
            }
        }
    

    如您所见,该方法需要一个 Date 对象(您从 Firebase 检索的内容)。然后它将删除大部分不相关的数据(在我的情况下)并只返回指定格式的日期和时间。

    (注意:在这个post 中,UPDATE 2020/01/17 是,一位同事指出,在 Android Studio 4.0 中,我们也可以在旧 API 中使用 Java 8(就像我的情况一样- API 21),但我没有深入研究具体的主题。你也可以检查一下:)

    【讨论】:

      猜你喜欢
      • 2020-10-22
      • 2021-02-19
      • 1970-01-01
      • 2018-03-20
      • 1970-01-01
      • 2019-11-01
      • 2019-01-31
      • 2020-05-06
      • 2021-12-31
      相关资源
      最近更新 更多