概要
DateTime <=> String の変換方法を忘れるのでメモ。
あと、関係するだろうTimeZoneとLocaleについても書いときます。
設定
flutter_localizationsを設定します。
intlライブラリを記述している例がありますが、不要です。
それはflutter_localizationsで含まれます。
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
変換方法
例えば、apiの戻り値のString日付をyyyy/MM/dd(E) HH:mm形式にしたい場合。
import "package:intl/intl.dart";
import 'package:intl/date_symbol_data_local.dart';
・・・
final String sentDateJst;
get sentDateFormatted {
initializeDateFormatting("ja_JP");
DateTime datetime = DateTime.parse(sentDateJst); // StringからDate
var formatter = new DateFormat('yyyy/MM/dd(E) HH:mm', "ja_JP");
var formatted = formatter.format(datetime); // DateからString
return formatted;
}
initializeDateFormattingの戻り値がFutureなので迷うと思うが、上記でできます。
TimeZoneについて
dartのDateTimeはimmutableです。なので一度作成されたDateTimeのTimeZoneの変更はできません。
ios/androidで設定されているtimezoneでインスタンスされます。公式に以下と書かれています。
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.
Once created, neither the value nor the time zone of a DateTime object may be changed.
例えば、JSTで設定されているOSの場合は、timeZoneName
で取得できる文字列はJSTになります。
toUTc()
メソッドを使えば、UTCの DateTime
が取得できます。
timeZoneOffset
の戻り値は、Duration
クラスで inHours
を呼べばJSTの場合は9が帰ってきます。
DateTimeのaddメソッドでは、この Duration
を指定できます。
DateTime hoge = DateTime.now().add(duration);
もし、APIの戻り値で年月日を別々に保持している場合でもDateTime.utcでインスタンスできます。
import "package:intl/intl.dart";
import 'package:intl/date_symbol_data_local.dart';
・・・
var utc = DateTime.utc(year, month, day);
var local = utc.toLocal();
そして現在の端末のtimezoneで表示したい場合は toLocal()
メソッドを呼び出し、DateFormat
を使ってフォーマットします。
UTCで保持しているAPIにPOSTしたい場合は、普通に toUTc()
の結果をAPI仕様に合わせてフォーマットすれば良いでしょう。
Localeについて
MaterialAppインスタンス時に指定しておいて、
import 'package:flutter_localizations/flutter_localizations.dart';
・・・
new MaterialApp(
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale("en", "US"),
const Locale("ja", "JP")
]
以下で取得できます。
Locale locale = Localizations.localeOf(context);
Localeクラスはflutterでは、UIのものっぽいので、厳格なアーキテクチャを望む場合は、enum化するロジックを書いて違うレイヤーに渡すのがベターだと思われます。
以下は解決済みです。
ちなみに日本語設定した時に、Androidではja_JPが取得できましたが、iosでは、常にen_USが返ってきました。
そんなバグがあるようです。