🕑

Cloud Firestore ODMでサーバータイムスタンプを使う方法

2024/03/28に公開
Github ywake/zenn

cloud_firestore_odm: ^1.0.0-dev.84で確認

実現したいこと

FlutterのCloud Firestore ODMでFirestoreを操作する際、createdAtupdatedAtなどのフィールドにサーバータイムスタンプを使いたい。
ODMを使わないならFieldValue.serverTimestamp()を直接使えばいいが、ODMにはそれらしいものがなかった。

解決方法

カスタムコンバーターを作成して、toJson()の際にFieldValue.serverTimestamp()に変換する。

class ServerTimestamp extends JsonConverter<DateTime, dynamic> {
  const ServerTimestamp();

  
  DateTime fromJson(dynamic json) => json == null
      ? DateTime.now()
      : const FirestoreDateTimeConverter().fromJson(json as Timestamp);
      // サーバータイムスタンプをセットする際に、リスナーが一瞬nullを受信することがある
      // のでその瞬間はクライアントの現在時間を使用

  
  dynamic toJson(DateTime object) => FieldValue.serverTimestamp();
}

使い方

class Task {
  Task({
    this.id,
    required this.title,
    required this.createdAt,
    required this.updatedAt,
  });

  ()
  final String? id;
  final String title;
  ()
  final DateTime createdAt;
  ()
  final DateTime updatedAt;
}

注意

.update()を使う際には問題ないが、.set()を使う際にはcreatedAtも更新されてしまうので注意が必要。
.set()にも対応するなら以下のようにして更新するときだけnullを渡すなどの工夫が必要。

class ServerTimestamp extends JsonConverter<DateTime?, dynamic> {
  const ServerTimestamp();

  
  DateTime? fromJson(dynamic json) => json == null
      ? DateTime.now()
      : const FirestoreDateTimeConverter().fromJson(json as Timestamp);

  
  dynamic toJson(DateTime? object) => object == null
	  ? FieldValue.serverTimestamp()
	  : const FirestoreDateTimeConverter().toJson(object);
}

class Task {
  Task({
    this.id,
    required this.title,
    this.createdAt,
    this.updatedAt,
  });

  ()
  final String? id;
  final String title;
  ()
  final DateTime? createdAt;
  ()
  final DateTime? updatedAt;
}

参考

https://github.com/FirebaseExtended/firestoreodm-flutter/issues/15

合わせて読みたい

https://zenn.dev/yucatio/articles/c5cc8718f54fd7


関連記事

Discussion