cocoa-mhlw / cocoa

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

接触一覧でのタイムゾーン変換が正しくないことがある

yoshitomo-g opened this issue · comments

不具合の内容 / Describe the bug

接触一覧での時刻表示は端末のタイムゾーン設定に従って変換された結果が使われるが、それが正しくない例があった。

Twitterで見かけたもので、自動設定で東京となっていたにもかかわらず、午前12時00分が起点になっている。
https://twitter.com/Tanukichi01/status/1515406675104366593

再現手順 / Steps to reproduce

不明。

期待される挙動 / Expected behavior

正しくタイムゾーンが変換される。

スクリーンショット / Screenshots

接触一覧

接触一覧

タイムゾーン設定(設定アプリの、「一般」→「日付と時刻」)

タイムゾーン設定

動作環境 / Environments

  • デバイス:iPhone11 Pro
  • OS:iOS 15.4.1
  • バージョン:COCOA v2.0.0

その他 / Additional context

確認をしたスレッド
https://twitter.com/yoshitomo_y/status/1515604339364048898


Internal IDs:

  • Bug 6804

補足情報として。
.NET 的に「0時(24時間表記)」=「午前12時」、「12時(24時間表記)」=「午後12時」 の表記になる様子。

UTC のまま出力されている?(考えにくいとは思う)

ご報告ありがとうございます。
コード上は、次のIExposureDataRepository.ConvertToTermで期間に変換しています。端末の設定に応じてタイムゾーンを変換しているのは .ToLocalTime()ですね。

public static string ConvertToTerm(DateTime utcDatetime)
{
var from = utcDatetime.Date.ToLocalTime();
var to = from.AddDays(1).ToLocalTime();
bool changeMonth = from.Month != to.Month;
bool changeYear = from.Year != to.Year;
string fromFormat = AppResources.ExposureDateFormatMonth;
string toFormat = AppResources.ExposureDateFormatDate;
if (changeMonth)
{
toFormat = AppResources.ExposureDateFormatMonth;
}
if (changeYear)
{
fromFormat = AppResources.ExposureDateFormatYear;
toFormat = AppResources.ExposureDateFormatYear;
}
string fromStr = string.Format(fromFormat, from.Year, from.Month, from.Day, from.Hour);
string toStr = string.Format(toFormat, to.Year, to.Month, to.Day, to.Hour);
return string.Format("{0} {1} {2}", fromStr, AppResources.ExposuresPageTo, toStr);
}

端末のタイムゾーンが、Xamarin(Mono)から、どのように認識されているのかに注目しています。
原因調査・解決と並行して、今すぐできる現象への対応としては、テキストの「設定されているタイムゾーン」に、具体的な時差情報を含めるというのも1つの手かと思います。

https://docs.microsoft.com/ja-jp/dotnet/api/system.timezoneinfo?view=net-5.0

  • TimeZoneInfo.Local.StandardName
  • TimeZoneInfo.Local.DisplayName

のどちらかを表示する手もあるかとは思いますが、分かりやすいかはちょっと疑問が残ります。

これ、「1回の接触」となっているので、COCOA v1.x での接触情報を v2.0.0 で見てるのかな?

現状、 COCOA v1.x で行った接触確認の記録を取りだしたときに、Timestamp の DateTimeKind が Local になっている可能性を考えています。 (あまり自信は無い)

COCOA v1.x での接触確認の結果は userExposureInformationList として取り扱われている。

foreach (var ei in userExposureInformationList.GroupBy(userExposureInformation => userExposureInformation.Timestamp))
{
var ens = new ExposureSummary()
{
Timestamp = ei.Key,
ExposureDate = IExposureDataRepository.ConvertToTerm(ei.Key),
};
ens.SetExposureCount(ei.Count());
exposures.Add(ens);
}

ViewModel で userExposureInformationList を取得している箇所。

var userExposureInformationList
= _exposureDataRepository.GetExposureInformationList(AppConstants.DaysOfExposureInformationToDisplay);

exposureInformation は JSON 形式で保存されているのでデシリアライズ。

var exposureInformationJson = _secureStorageService.GetValue<string>(PreferenceKey.ExposureInformation, null);
if (!string.IsNullOrEmpty(exposureInformationJson))
{
result = JsonConvert.DeserializeObject<List<UserExposureInfo>>(exposureInformationJson);
}

Json.NET での DateTime 型のデシリアライズについて。
#64 (comment)

この想定が正しい場合、ConvertToTerm に渡される引数も(変数名とは違い)ローカル時刻。
ローカル時刻のまま日付操作を行ってしまうので、頂いたスクリーンショットのような結果が予測されます。
(ローカル時刻に対する toLocalTime() は何もしない為)

ありがとうございます。
シリアライズの時にタイムゾーンが失われ、デシリアライズの過程でDateTimeKind.Localとなっている可能性ですね。その場合、再現性という意味では100%になると思うのですが、ちゃんと表示されてるケースもあるのが気になります。

https://twitter.com/aurata4/status/1515088238108897283

Issueに引用いただいているTanukiti01さんは、iOS版のCOCOAをお使いですね。Tweet時点でのスクリーンショットではENv1での接触記録だけが表示されていますが、次のタイミングでENv2での接触記録が出る可能性があります。
これはiOS版はENv2に切り替えた後、ENv1の接触についてもExposureWindowとDailySummaryが得られるのですが、新しいENv2で得られた接触と、ENv1のころの接触は、タイムスタンプが同じでも実態が同じと区別することができないのでそのまま表示しているためです。

次に出てくる(かもしれない)ENv2の行の日時がどうなっているかで、ExposureInformation固有の問題なのか、C#のToLocal()の不調なのか(ENv2の行も12からになっていればC#起因と判定できる)がわかると考えています。

こちら、現時点では再現条件が不明と認識していますが問題無いでしょうか。
私の観測範囲では(自身の端末を含め)同様の事象は発見できていないです。

はい。再現条件は不明。実際に発生している端末でアプリからどのタイムゾーンが表示されるかを確認すれば何か分かるかも。というフェーズです。