Flutter应用程序错误-类型'Timestamp'不是类型'DateTime'的子类型

时间:2018-10-25 19:26:30

标签: dart flutter

我正在获取数据云存储,并尝试使用以下代码在我的应用中显示。

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

我正在使用timeago飞镖包来格式化它。但是,在更新到最新的Cloud Firestore插件后,出现了此错误-

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

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

16 个答案:

答案 0 :(得分:13)

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

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

希望,它将对某人有所帮助。

答案 1 :(得分:3)

我认为这更可靠

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

答案 2 :(得分:2)

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);
}

答案 3 :(得分:1)

DateTime.fromMillisecondsSinceEpoch(timeStamp);
DateTime.fromMicrosecondsSinceEpoch(timeStamp);

答案 4 :(得分:1)

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

这对我有用:-

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

答案 5 :(得分:1)

如果您使用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 :(得分:0)

var date = DateTime.fromMillisecondsSinceEpoch(timestamp)

答案 7 :(得分:0)

出于某些有趣的原因,我无法在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'])

答案 8 :(得分:0)

您可以尝试一下。

timeago.format(DateTime.tryParse(timestamp))

就像您一样

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

答案 9 :(得分:0)

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 :(得分:0)

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

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

答案 11 :(得分:0)

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)

答案 12 :(得分:0)

这也可能是一个错误,因为在数据库或Firebase中缺少某种类型或

上的其他名称

答案 13 :(得分:0)

这是不相干的,但是对于那些使用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;
    }
  }
}

答案 14 :(得分:0)

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

来自后端,我收到此回复

"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;
}

答案 15 :(得分:0)

为了记录,如果您使用冻结,这对我有用:

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');
}