Closed22

DartのDateTimeについて調べる

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

誕生日をUTCで表示

void main() {
  final birthday = DateTime.utc(1987,8,27);
  print(birthday); // 1987-08-27 00:00:00.000Z
}

ちゃんとZがついている

そして月がJavaScriptと使って1スタートなのが嬉しい

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

文字列からパース

void main() {
  final birthday = DateTime.parse('1987-08-27T00:00:00Z');
  print(birthday); // 1987-08-27 00:00:00.000Z
}

間のTはあってもなくても良い

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

DateTimeオブジェクトはUTCかローカルタイムにアンカーされると書いてある

A DateTime object is anchored either in the UTC time zone or in the local time zone of the current computer when the object is created.

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

DateTimeオブジェクトは時刻やタイムゾーンを後から変えられない

Once created, neither the value nor the time zone of a DateTime object may be changed.



void main() {
  final birthday = DateTime.parse('1987-08-27T00:00:00Z');
  birthday.day = 10;
  print(birthday); // 1987-08-27 00:00:00.000Z
}

エラーメッセージ

Error compiling to JavaScript:
Info: Compiling with sound null safety
lib/main.dart:5:12:
Error: The setter 'day' isn't defined for the class 'DateTime'.
 - 'DateTime' is from 'dart:core'.
  birthday.day = 10;
           ^^^
Error: Compilation failed.

セッターが無いと言われている

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

yearなどのプロパティで個々の数字にアクセスできる

void main() {
  final birthday = DateTime.parse('1987-08-27T00:00:00Z');
  print(birthday.year); // 1987
  print(birthday.month); // 8
  print(birthday.day); // 27
  print(birthday.hour); // 0
  print(birthday.minute); // 0
  print(birthday.second); // 0
}

hour以下も単数系、JavaScriptとは違う

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

DateTimeには定数がある

void main() {
  print(DateTime.january); // 1
  print(DateTime.monday); // 1
  print(DateTime.sunday); // 7
}

月は1スタート、曜日は月曜日からの1スタート

ちなみに曜日はweekdayプロパティを使ってアクセスできる

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

UTCかどうかはisUtcプロパティを使う

void main() {
  final now = DateTime.now();
  final birthday = DateTime.utc(1987, 8, 27);
  print(now.isUtc); // false
  print(birthday.isUtc); // true
}
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

toLocaltoUtcメソッドを使って相互に変換できる

void main() {
  final now = DateTime.now();
  final birthday = DateTime.utc(1987, 8, 27);
  print(now.toUtc()); // 2022-11-04 01:33:33.183Z
  print(birthday.toLocal()); // 1987-08-27 09:00:00.000
}
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

timeZoneNametimeZoneOffsetプロパティを使うとタイムゾーンの名前やオフセットが確認できる。

void main() {
  final now = DateTime.now();
  final birthday = DateTime.utc(1987, 8, 27);

  print(now.timeZoneName); // 日本標準時
  print(now.timeZoneOffset); // 9:00:00.000000
  
  print(birthday.timeZoneName); // UTC
  print(birthday.timeZoneOffset); // 0:00:00.000000
}
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

isBeforeisAfterメソッドを使うと後先を確認できる

void main() {
  final now = DateTime.now();
  final birthday = DateTime.utc(1987, 8, 27);

  print(now.isAfter(birthday)); // true
  print(now.isBefore(birthday)); // false
}

isAtSameMomentAsメソッドを使うと同じか否かを確認できる

ローカルかUTCかは考慮されない

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

Durationを使うと足し算(add)や引き算(subtract)ができる、便利

void main() {
  final birthday = DateTime.utc(1987, 8, 27);
  print(birthday.add(Duration(days: 100))); // 1987-12-05
}

Durationの引数は複数形、私の100日記念は12/5だった模様

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

日付を比較してDurationを作成することも可能

void main() {
  final birthday = DateTime.utc(1987, 8, 27);
  final birthdaySister = DateTime.utc(1985, 12, 9);
  print(birthday.difference(birthdaySister)); // 15024:00:00.000000
  print(birthday.difference(birthdaySister).inDays); // 626
}

私は姉の626日後に誕生したようだ

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

以上がDateTimeクラスのページの内容、説明が素晴らしいので機能がほぼ網羅されている

残りのプロパティやメソッドについても調べていく

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

その他のコンストラクタ

  • DateTime:ローカルタイムであることを除いてDateTime.utcと同じ
  • DateTime.fromMicrosecondsSinceEpoch:1970-01-01Zからのマイクロ秒で指定
  • DateTime.fromMillisecondsSinceEpoch constructor:1970-01-01Zからのミリ秒で指定

SinceEpoch系のメソッドは第2引数としてisUtcを受け取る、文字通りUtcであるか否か

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

toIso8601Stringを使うとISO8601日次文字列に変換できる

void main() {
  final birthday = DateTime.utc(1987, 8, 27);
  print(birthday.toIso8601String()); // 1987-08-27T00:00:00.000Z
}

API通信などの場面で便利そう

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

比較演算子==はタイムゾーンまでチェックするので厳格

void main() {
  final birthday = DateTime.utc(1987, 8, 27);
  final birthdayLocal = DateTime(1987, 8, 27, 9, 0, 0);
  print(birthday == birthdayLocal); // false
  print(birthday.isAtSameMomentAs(birthdayLocal)); // true
}
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

DateTime.parseDateTime.tryParseメソッドは文字列をパースしてDateTimeオブジェクトを作成する

parseの方はパースできないと例外を発生させるが、tryParseの方はNullを返す

かなり幅広いフォーマットに対応している

"2012-02-27"
"2012-02-27 13:27:00"
"2012-02-27 13:27:00.123456789z"
"2012-02-27 13:27:00,123456789z"
"20120227 13:27:00"
"20120227T132700"
"20120227"
"+20120227"
"2012-02-27T14Z"
"2012-02-27T14+00:00"
"-123450101 00:00:00 Z": in the year -12345.
"2002-02-27T14:00:00-0500": Same as "2002-02-27T19:00:00Z"
このスクラップは2023/01/10にクローズされました