【问题标题】:Flutter app error - type 'Timestamp' is not a subtype of type 'DateTime'Flutter 应用程序错误 - 类型“时间戳”不是“日期时间”类型的子类型
【发布时间】:2019-03-30 12:06:54
【问题描述】:

我正在获取数据 cloud firestore 并尝试使用以下代码在我的应用中显示。

new Text(timeago.format(document.data['tripDoc']['docCreatedOn'])),

我正在使用timeago dart 包来格式化它。但是,在更新到最新的 cloud firestore 插件后,我收到了这个错误 -

Another exception was thrown: type 'Timestamp' is not a subtype of type 'DateTime'

无法理解如何将此“TimeStamp”对象解析为“DateTime”。因为timeago插件需要DateTime对象格式的数据。

【问题讨论】:

    标签: flutter dart google-cloud-firestore


    【解决方案1】:

    .toDate() 为我工作。现在修改后的代码是-

    new Text(timeago.format(document.data['tripDoc']['docCreatedOn'].toDate()))
    

    希望对某人有所帮助。

    【讨论】:

      【解决方案2】:

      添加 toDate() 方法。它将起作用

      DateTime dateTime = documents[i].data["duedate"].toDate();
      

      【讨论】:

        【解决方案3】:

        Ios 和 Android 不会收到相同的类型。 Ios 将时间戳作为 TimeStamp 接收,而 Android 已经将它作为 DateTime 接收。所以为了解决这个问题,我刚刚创建了这个小函数。这将返回一个 DateTime 并让我们使用它的格式等。

        import 'dart:io';
        
        import 'package:cloud_firestore/cloud_firestore.dart';
        
        DateTime parseTime(dynamic date) {
          return Platform.isIOS ? (date as Timestamp).toDate() : (date as DateTime);
        }
        

        【讨论】:

          【解决方案4】:

          我觉得这个比较靠谱

          DateTime updateDateTime = DateTime.fromMillisecondsSinceEpoch(
                  map['updatedatetime'].millisecondsSinceEpoch);
          

          【讨论】:

            【解决方案5】:

            如果您使用JsonSerializable,请使用JsonConverter

            class TimestampConverter implements JsonConverter<DateTime, Timestamp> {
              const TimestampConverter();
            
              @override
              DateTime fromJson(Timestamp timestamp) {
                return timestamp.toDate();
              }
            
              @override
              Timestamp toJson(DateTime date) => Timestamp.fromDate(date);
            }
            
            @JsonSerializable()
            class User{
              final String id;
              @TimestampConverter()
              final DateTime timeCreated;
            
              User([this.id, this.timeCreated]);
            
              factory User.fromSnapshot(DocumentSnapshot documentSnapshot) =>
                  _$UserFromJson(
                      documentSnapshot.data..["_id"] = documentSnapshot.documentID);
            
              Map<String, dynamic> toJson() => _$UserToJson(this)..remove("_id");
            }
            

            【讨论】:

              【解决方案6】:
              DateTime.fromMillisecondsSinceEpoch(timeStamp);
              DateTime.fromMicrosecondsSinceEpoch(timeStamp);
              

              【讨论】:

                【解决方案7】:

                试试document.data["data"].microsecondsSinceEpoch

                这对我有用:-

                User.fromDocument(DocumentSnapshot document){
                dataNasc = DateTime.fromMicrosecondsSinceEpoch(document.data["data"].microsecondsSinceEpoch);
                }
                

                【讨论】:

                  【解决方案8】:
                  var date = DateTime.fromMillisecondsSinceEpoch(timestamp)
                  

                  【讨论】:

                    【解决方案9】:

                    Firestore 正在返回一个 Timestamp 对象,该对象由秒和纳秒组成。奇怪的是,在 iOS 上,您确实可以只使用 .toDate() 并且它可以工作。但这在 Android 上会中断,因为 toDate() 不是一种方法。因此,您可以根据需要进行平台检查,但通用解决方案是使用 Firestore 的时间戳:

                    import 'package:cloud_firestore/cloud_firestore.dart';
                    
                    DateTime _convertStamp(Timestamp _stamp) {
                    
                      if (_stamp != null) {
                    
                        return Timestamp(_stamp.seconds, _stamp.nanoseconds).toDate();
                    
                        /*
                        if (Platform.isIOS) {
                          return _stamp.toDate();
                        } else {
                          return Timestamp(_stamp.seconds, _stamp.nanoseconds).toDate();
                        }
                        */
                    
                      } else {
                        return null;
                      }
                    }
                    

                    然后将你的模型传递给它:

                      SomeModel.fromJson(Map<String, dynamic> parsedJson) {
                        updatedAt = _convertStamp(parsedJson['updatedAt']);
                      }
                    

                    【讨论】:

                      【解决方案10】:

                      Cloud Firebase 时间戳字段类型具有以下结构:

                      Timestamp (Timestamp(seconds=1561186800, nanoseconds=0))
                      hashCode:423768083
                      microsecondsSinceEpoch:1561186800000000
                      millisecondsSinceEpoch:1561186800000
                      nanoseconds:0
                      runtimeType:Type (Timestamp)
                      seconds:1561186800
                      _seconds:1561186800
                      _nanoseconds:0
                      

                      因此您可以使用微秒或毫秒:

                      DateTime.fromMillisecondsSinceEpoch(data['tripDoc']['docCreatedOn'].millisecondsSinceEpoch)
                      

                      DateTime.fromMicrosecondsSinceEpoch(data['tripDoc']['docCreatedOn'].microsecondsSinceEpoch)
                      

                      【讨论】:

                        【解决方案11】:

                        出于一些有趣的原因,我不能在 Android 上使用 toDate()。必须在 iOS 上使用它。所以我不得不使用这样的平台检查:

                        Theme.of(context).platform == TargetPlatform.iOS
                          ? DateFormat('dd MMM kk:mm').format(document['timestamp'].toDate())
                          : DateFormat('dd MMM kk:mm').format(document['timestamp'])
                        

                        【讨论】:

                          【解决方案12】:

                          你可以试试这个。。

                          timeago.format(DateTime.tryParse(timestamp))
                          

                          和你的一样

                            timeago.format(DateTime.tryParse(document.data['tripDoc']['docCreatedOn']))
                          

                          【讨论】:

                            【解决方案13】:

                            这也可能是一个错误,因为在数据库或 Firebase 中存在某些类型丢失或名称不同

                            【讨论】:

                            • 你能详细说明你的答案吗?正如这里所写,它似乎更像是评论而不是提出解决方案的答案。
                            【解决方案14】:

                            这无关紧要,但对于那些使用 Timestamp (cloud_firestore) 而不是 DateTime 的人来说,您可能会得到

                            ' 不是 'Timestamp' 类型的子类型

                            class MyUser {
                              String uid;
                              String email;
                              Timestamp firstJoined;
                              
                              MyUser.fromJson(Map<String, dynamic> data) {
                                this.uid = data['uid'] ?? '';
                                this.email = data['email'] ?? '';
                                // PARSE FIRESTORE TIMESTAMP
                                if (data['firstJoined'] != null) {
                                    this.firstJoined = Timestamp(
                                        data['firstJoined']['_seconds'],
                                        data['firstJoined']['_nanoseconds'],
                                    );
                                } else {
                                    this.firstJoined=null;
                                }
                              }
                            }
                            

                            【讨论】:

                              【解决方案15】:

                              针对该错误,我在模型类中进行了更改。

                              我收到了来自后端的回复

                              "reported_date": "2021-02-19T05:45:57.434150Z",
                              

                              改变

                              reportedDate = json['reported_date']
                              

                              reportedDate = json['reported_date'] == null ? null : DateTime.parse(json['reported_date'] as String);
                              

                              这解决了我的问题。

                              解析后可以使用任何格式 to read about formates

                              下面的一些例子,我正在测试以供参考

                              ///return in 12:08 PM format
                              static String returnTime(DateTime dt) {
                                final DateFormat formatter = DateFormat('h:mm a');
                                String time = formatter.format(dt);
                                return time;
                              }
                              
                              ///return in Thu, Feb 18 format
                              String returnDate(DateTime dt) {
                                final DateFormat formatter = DateFormat('EEE, MMM d');
                                String date = formatter.format(dt);
                                return date;
                              }
                              
                              ///return day (Thu, Feb 18, will return 18)
                              String standaloneDay(DateTime dt) {
                                final DateFormat formatter = DateFormat('c');
                                String date = formatter.format(dt);
                                return date;
                              }
                              

                              【讨论】:

                                【解决方案16】:

                                为了记录,如果你使用 freezed,这对我有用:

                                import 'package:cloud_firestore/cloud_firestore.dart';
                                import 'package:flutter/cupertino.dart';
                                import 'package:freezed_annotation/freezed_annotation.dart';
                                import 'package:flutter/foundation.dart';
                                
                                part 'activity_card_model.freezed.dart';
                                part 'activity_card_model.g.dart';
                                
                                DateTime _createdAtFromJson(Timestamp timestamp) => timestamp.toDate();
                                Timestamp _createdAtToJson(DateTime date) => Timestamp.fromDate(date);
                                DateTime _updatedAtFromJson(Timestamp timestamp) => timestamp.toDate();
                                Timestamp _updatedAtToJson(DateTime date) => Timestamp.fromDate(date);
                                
                                @freezed
                                abstract class ActivityCard implements _$ActivityCard {
                                  const ActivityCard._();
                                
                                  const factory ActivityCard({
                                    @Default(true) bool active,
                                    @Default('other') String category,
                                    @JsonKey(name: 'created_at', fromJson: _createdAtFromJson, toJson: _createdAtToJson)
                                        required DateTime createdAt,
                                    required String description,
                                    required String heading,
                                    String? id,
                                    @JsonKey(name: 'image_name') @Default('') String imageName,
                                    @JsonKey(name: 'img_src') @Default('') String imageURL,
                                    @JsonKey(name: 'link') String? linkURL,
                                    @JsonKey(name: 'link_description') String? linkDescription,
                                    String? subheading,
                                    @JsonKey(name: 'updated_at', fromJson: _updatedAtFromJson, toJson: _updatedAtToJson)
                                        required DateTime updatedAt,
                                  }) = _ActivityCard;
                                
                                  factory ActivityCard.fromFirestore(DocumentSnapshot doc) {
                                    Map<String, dynamic> json = doc.data as Map<String, dynamic>;
                                    return ActivityCard.fromJson(json);
                                  }
                                
                                  factory ActivityCard.fromJson(Map<String, dynamic> json) =>
                                      _$ActivityCardFromJson(json);
                                
                                  factory ActivityCard.fromDocument(
                                      DocumentSnapshot<Map<String, dynamic>> doc) {
                                    final data = doc.data()!;
                                    return ActivityCard.fromJson(data).copyWith(id: doc.id);
                                  }
                                
                                  Map<String, dynamic> toDocument() => toJson()..remove('id');
                                }
                                

                                【讨论】:

                                  猜你喜欢
                                  • 2019-08-05
                                  • 2021-05-09
                                  • 2019-12-21
                                  • 2021-11-26
                                  • 1970-01-01
                                  • 2018-09-01
                                  • 1970-01-01
                                  • 2016-12-14
                                  • 2010-10-05
                                  相关资源
                                  最近更新 更多