👫

extension type でDateTimeを使う

2024/10/28に公開

Tips🔅

Dart3.0から導入されたextension typeを使った例がXで紹介されていて気になって使ってみた。
https://x.com/ChrisMarxDev/status/1849713213715235200

Don't be like me and try to use DateTime to model a Date.
Use extension types.

私のように DateTime を使用して Date をモデル化しようとしないでください。

Oooh that’s a cool idea. I always make a .startOfDay extension getter to do days

Yea same, but I kept forgetting to add it ☠️

クールなアイデアだね。僕はいつも.startOfDayの拡張子ゲッターを作って日数を指定しているんだ。

そうだね、でもそれを追加するのをずっと忘れてたんだ。☠️

これだけだとわからないので使用例を書いてみる

extension type Date._(DateTime dateTime) {
  Date(DateTime dateTime)
  : this._(DateTime(dateTime.year, dateTime.month, dateTime.day));

  Date.today() : this(DateTime.now());

  bool operator >(Date other) => dateTime.isAfter(other.dateTime);
  bool operator <(Date other) => dateTime.isBefore(other.dateTime);
}

Dart 3.0で導入された新機能について、extension typeを使った日付操作の例を元に説明させていただきます。

まず、示していただいたコードの主要なポイントを説明します:

  1. Extension Typeの基本
extension type Date._(DateTime dateTime) {
  // 実装
}

これはDart 3.0の新機能で、既存の型(この場合はDateTime)に新しい機能を追加しながら、型の安全性を保証します。

  1. 活用方法の具体例をいくつか示します:
// 日付の比較や演算を簡潔に書ける
void example() {
  final today = Date.today();
  final tomorrow = Date(DateTime.now().add(Duration(days: 1)));
  
  print(today < tomorrow); // true
  
  // 年齢計算などに活用
  final birthDate = Date(DateTime(1990, 1, 1));
  final now = Date.today();
}

Dart 3.0の新機能を活用するための追加のテクニック:

  1. パターンマッチング:
extension type Date._(DateTime dateTime) {
  // コンストラクタ
  Date(DateTime dateTime)
      : this._(DateTime(dateTime.year, dateTime.month, dateTime.day));

  Date.today() : this(DateTime.now());

  // ゲッターでdateTimeの各フィールドにアクセス
  int get year => dateTime.year;
  int get month => dateTime.month;
  int get day => dateTime.day;

  // 比較演算子
  bool operator >(Date other) => dateTime.isAfter(other.dateTime);
  bool operator <(Date other) => dateTime.isBefore(other.dateTime);

  // パターンマッチングを使用する例
  String checkDate() {
    return switch (dateTime) {
      DateTime(year: 2024) => '今年の日付です',
      _ => 'その他の年の日付です'
    };
  }

  // 季節を判定する例
  String getSeason() {
    return switch (month) {
      >= 3 && <= 5 => '春',
      >= 6 && <= 8 => '夏',
      >= 9 && <= 11 => '秋',
      _ => '冬'
    };
  }

  // 祝日かどうかをチェックする例
  bool isHoliday() {
    return switch ((month, day)) {
      (1, 1) => true,    // 元日
      (5, 5) => true,    // こどもの日
      _ => false
    };
  }
}

// 使用例
void main() {
  final today = Date.today();
  final someDate = Date(DateTime(2024, 3, 1));
  
  // 日付の比較
  print(today > someDate ? '今日の方が新しい' : '指定日の方が新しい');
  
  // パターンマッチングのテスト
  print(someDate.checkDate());  // "今年の日付です"
  
  // 季節の判定
  print(someDate.getSeason());  // "春"
  
  // 祝日チェック
  print(someDate.isHoliday() ? '祝日です' : '平日です');
}
  1. Records との組み合わせ:
extension type Date._(DateTime dateTime) {
  Date(DateTime dateTime)
  : this._(DateTime(dateTime.year, dateTime.month, dateTime.day));

  Date.today() : this(DateTime.now());

  bool operator >(Date other) => dateTime.isAfter(other.dateTime);
  bool operator <(Date other) => dateTime.isBefore(other.dateTime);
}

(Date start, Date end) getDateRange() {
  final start = Date.today();
  final end = Date(DateTime.now().add(Duration(days: 7)));
  return (start, end);
}

void main() {
  var getDate = getDateRange();
  print(getDate);// (2024-10-28 00:00:00.000, 2024-11-04 00:00:00.000)
}

これらの機能を活用することで:

  • より型安全なコードが書ける
  • 日付操作が直感的に
  • コードの可読性が向上
  • バグの発生リスクを低減

実行してみる

extension type Date._(DateTime dateTime) {
  Date(DateTime dateTime)
  : this._(DateTime(dateTime.year, dateTime.month, dateTime.day));

  Date.today() : this(DateTime.now());

  bool operator >(Date other) => dateTime.isAfter(other.dateTime);
  bool operator <(Date other) => dateTime.isBefore(other.dateTime);
}

// 日付の比較や演算を簡潔に書ける
void example() {
  final today = Date.today();
  final tomorrow = Date(DateTime.now().add(Duration(days: 1)));
  
  print(today < tomorrow); // true
  
  // 年齢計算などに活用
  final birthDate = Date(DateTime(1990, 1, 1));
  print(birthDate);
  final now = Date.today();
  print(now);
}

void main(List<String> args) {
  example();
}

log:

true
1990-01-01 00:00:00.000
2024-10-28 00:00:00.000

Exited.

最後に

Dart3.0は去年でたのだったかな。もっと普及してくれるといいですね。慣れないと分かりずらいコードになるが😇

Discussion