You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Firestore FieldValue中获取日期值?解决类型转换报错

问题分析与解决方案

问题根源

  1. 转换器逻辑错误:你的ServerTimestampConverter在读取Firestore文档时,不管输入的json实际是Timestamp类型,都强制返回FieldValue.serverTimestamp(),导致类型不匹配报错。
  2. DTO字段类型不兼容:写入时用FieldValue标记服务器时间,但读取时Firestore返回的是Timestamp,单一的FieldValue类型无法同时兼容写入标记和读取结果两种场景。

解决方案

1. 修正ServerTimestampConverter实现

让转换器在读取文档时返回Firestore实际存储的Timestamp,在写入文档时返回FieldValue.serverTimestamp(),适配两种场景:

class ServerTimestampConverter implements JsonConverter<Timestamp, Object> {
  const ServerTimestampConverter();

  @override
  Timestamp fromJson(Object json) {
    // 读取时直接返回Firestore的Timestamp类型
    return json as Timestamp;
  }

  @override
  Object toJson(Timestamp timestamp) {
    // 写入时返回服务器时间戳标记,让Firestore自动生成时间
    return FieldValue.serverTimestamp();
  }
}

2. 调整DTO字段类型与转换逻辑

将creationTimestamp的类型改为Timestamp,读取时直接拿到Firestore返回的时间戳,写入时转换器自动替换为服务器时间标记:

@freezed
abstract class KeekzCardDto implements _$KeekzCardDto {
  const factory KeekzCardDto({
    required String keekzDescription,
    @ServerTimestampConverter() required Timestamp creationTimestamp,
    required String keekzCaption,
    required bool freeOfCharge,
    required bool handicapAccessible,
    required AddressDto address,
  }) = _KeekzCardDto;

  //! To Domain Models
  KeekzCard toDomain() {
    return KeekzCard(
      freeOfCharge: freeOfCharge,
      handicapAccessible: handicapAccessible,
      address: address.toDomain(),
      caption: KeekzCardCaption(keekzCaption),
      description: KeekzCardDescription(keekzDescription),
      creationTimeStamp: DateTimeStamp(
        creationTimestamp.toDate().toString(),
      ),
    );
  }
}

3. 写入文档的正确姿势

创建DTO实例时,creationTimestamp可以传任意临时Timestamp(比如Timestamp.now()),转换器会自动在写入时替换为Firestore服务器时间标记:

// 示例:创建DTO并写入Firestore
final dto = KeekzCardDto(
  keekzDescription: "示例描述",
  creationTimestamp: Timestamp.now(), // 该值会被转换器自动替换
  keekzCaption: "示例标题",
  freeOfCharge: true,
  handicapAccessible: false,
  address: AddressDto(...),
);

FirebaseFirestore.instance.collection("cards").add(dto.toJson());

额外优化(可选)

如果想让业务层直接使用DateTime而非Timestamp,可以修改转换器直接处理DateTime与Firestore类型的转换:

class ServerTimestampConverter implements JsonConverter<DateTime, Object> {
  const ServerTimestampConverter();

  @override
  DateTime fromJson(Object json) {
    return (json as Timestamp).toDate();
  }

  @override
  Object toJson(DateTime date) {
    return FieldValue.serverTimestamp();
  }
}

对应的DTO字段改为required DateTime creationTimestamp,业务层转换逻辑也更简洁:

creationTimeStamp: DateTimeStamp(creationTimestamp.toString()),

内容的提问来源于stack exchange,提问作者SRel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 05:12:54