3

ユーザーの現在の時刻と、世界中のさまざまな都市を表示する Windows ストア時計アプリを構築しています。

当初は、Google などのタイムゾーン Web サービスを完全に使用する予定でしたが、無料アカウントで許可されるリクエストの数と、有料アカウントを取得するためのコストを検討した結果、別の方法を見つけたほうがよいと感じました。家を抵当に入れなくても解決。

いろいろと調べてみると、John Skeet とチームによる優れた NodaTime ライブラリが見つかりました。ドキュメントとここでスタックオーバーフローを掘り下げた後、私の頭はまだすべての日時とタイムゾーンに関連する用語と変換方法で賑やかです。とにかく、私は2つのオプションでこれを行うことができると思いました:

オプション 1 : DateTime.Now を使用して現在のシステム時刻を取得し、次のように nodatime を使用して他のゾーンの時刻を取得します (SO に関する別の質問への返信で Matt Johnson によって提供されたコードに基づく):

DateTimeZone homeZone = DateTimeZoneProviders.Tzdb["Asia/Colombo"];
LocalDateTime homeTime = LocalDateTime.FromDateTime(DateTime.Now);
ZonedDateTime homeTimeInZone = homeTime.InZoneStrictly(homeZone);
TbTime1.Text = "Home time is: " + homeTimeInZone.ToDateTimeOffset();

DateTimeZone timeZone1 = DateTimeZoneProviders.Tzdb["Australia/Perth"];
ZonedDateTime timeZone1Time = homeTimeInZone.WithZone(timeZone1);
TbTime2.Text = "Timezone 1 time is: " + timeZone1Time.ToDateTimeOffset();

オプション 2 : さらに調べたところ、この解決策を見つけ、次のようにもうまく機能すると感じました。

public ZonedDateTime GetTimeInTimeZone(string timeZone)
{
    // Timezone is olson timezone e.g. "Asia/Colombo"
    Instant now = SystemClock.Instance.Now;
    var zone = DateTimeZoneProviders.Tzdb[timeZone];
    ZonedDateTime zonedDateTime = now.InZone(zone);
    return zonedDateTime;
 }

ここで質問に答えてみましょう: 上記の両方のオプションでは、DateTime.NowまたはSystemClock.Instance.Nowのいずれかに依存して、最初にユーザーのシステム時刻を識別し、次にそれを必要なタイムゾーンの都市時間に変換します。しかし、ユーザーのシステムが正しい時刻に設定されていない場合はどうなるでしょうか? 私は信じています(間違っている場合は修正してください)DateTime.NowとSystemClock.Instance.Nowは両方ともシステムクロックを使用して現在の時刻を取得していますか? システム時刻が正しく設定されていないと仮定すると、ユーザーのシステム時刻に依存しているため、タイムゾーンを変換すると他の都市の時刻が間違って表示されるだけです。

このような場合、システム クロックに依存せずにユーザーの現在の時刻を確立するにはどうすればよいですか? 緯度/経度を使用してユーザーの現在のタイムゾーンを取得するために Web サービスを使用するように戻す必要がありますか、またはオフラインで作業できる NodaTime などを使用するより良いオプションはありますか? ありがとう。

4

2 に答える 2

4

いくつかのポイント:

  • 使用を避けるDateTime.Now

    • すでにローカル タイム ゾーンに変換されているため、DST フォールバック移行中に結果があいまいになる可能性があります。
    • Noda Time を使用せずに正確で明確な瞬間を取得する必要がある場合は、 を使用しますDateTime.UtcNow
    • DateTimeOffset.UtcNow、またはを使用することもできますDateTimeOffset.Now。オフセットが含まれている場合、あいまいさはありません。
    • 私のブログ の The Case Against DateTime.Nowも参照してください。

  • Noda Time では、それがインターフェースSystemClock.Instanceの実装であることを認識してください。IClock必要に応じて単体テストの実装を置き換えることができるように、可能な限りインターフェイスに対してコーディングする必要があります。最も単純な例では、を呼び出しても何も問題SystemClock.Instance.Nowはありませんが、テストが容易ではありません。

  • どのタイムゾーン入力を使用するかは、アプリケーションの要件に完全に基づいています。

    • システムが正しいゾーンに設定されていることに依存できる場合は、次のコマンドで取得できます

      DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
      
    • システムのタイムゾーンが正しく設定されていることに依存できない場合は、他の入力ソースを検討することをお勧めします。

    • GPS座標について言及しました。おそらくモバイルデバイスからそれを持っている場合は、それをタイムゾーンに解決するためのソリューションがあります. いくつかのオプションについては、こちらを参照してください。野田タイムはこの点であなたを助けることができません.

    • アプリのユーザーに、ドロップダウン リストまたは地図からタイム ゾーンを選択するよう求めることも検討してください。HTML/JS 用の地図ベースのタイム ゾーン ピッカーがここここにあります。(それらが WinJS ベースの Windows ストア アプリで機能するかどうかはわかりません。また、XAML ベースのソリューションをすぐに使用できるかどうかもわかりません。)

  • クロックの実際の時刻が間違って設定されている場合、タイム スタンプを取得するために別のサーバーにアクセスする以外に、できることはあまりありません。ほとんどの場合、オペレーティング システムが既にタイム サーバーと同期されていることに依存する必要があります。

    • 外部サービスとの同期必要な場合、それは困難な場合があります。伝送遅延の測定と補償を含め、NTP を適切に実装するものが必要です。これは簡単ではなく、おそらく外部ライブラリが必要です。私はお勧めするオフハンドを知りません。

    • Web サービスにアクセスして現在の時刻を返すことは、サーバーがその応答を送信するのにかかる時間を補償しないため、必ずしもあなたが思っているほど正確であるとは限りません。

    • GPS 受信機を備えたデバイスで実行している場合、GPS 信号から受信した正確なタイムスタンプを提供できることは技術的に可能です。それが Windows ストア API 経由で取得および使用できるかどうかはわかりません。MSDN でいくつかの参照を確認しましたが、空になりました。

  • あなたが提供した 2 つのコード サンプルに関して、彼らは少し異なることをしていますが、オプション 2 を使用します。よりクリーンで、純粋な Noda Time です。

于 2013-09-18T16:20:55.983 に答える
2

通常、時計が表示する正確な現地時間に頼ることができます。どの Windows マシンも、タイム サーバーと通信するように設定されています。デフォルトは time.windows.com です。ユーザーは、家の残りの時計との不一致に気付くでしょう。夏時間への移行日を間違える可能性は確かにあります。ただし、ユーザーの設定を覆したくない場合は、タイムゾーンの境界に近く、DST をオプトアウトしている郡に住んでいる可能性や、アメリカ インディアンの部族地域など、独自のルールを作成したばかりの場所に住んでいる可能性があります。

世界の遠隔地についてそのような決定を下すことは、まったく別のワックスボールです. 注目に値するのはサモア島で、2011 年にはタイムゾーンを飛び越え、UTC-11 から UTC+13 まで日付変更線を越えました。夏時間の規則は、常に地方の政治的決定の影響を受けます。地元の新聞のニュースのトップにはなりません。それがWebサービスになる可能性はいくらかあります。都市をタイムゾーンにマッピングすることは、それ自体が大規模なデータベースを必要とするものです。絶対的な精度が必要な場合は、本当にサービスが必要です。

于 2013-09-18T13:49:51.080 に答える