3

私はフォボスのドキュメントを読んでいます。一部のメソッドのロジックを理解できないことがあります。

デートロール

指定された年数または月数をこの Date に追加します。負の数は減算されます。ローリングと追加の違いは、ローリングは大きなユニットには影響しないということです。

フォボスはよく考えられていないのかもしれません。それがどこで役立つのか理解していないのかもしれません。

たとえば、2013-07-01 に 200 日を追加すると、2014 年になると予想されますが、2013 年にはなりません。

ロジックを説明できる人はいますか?

4

2 に答える 2

5

したがって、短い答えは、Adamが正しいrollということです。日付ピッカーや同様のユースケースaddを処理するために特別に存在し、月と年を処理するために特別に存在Durationします。開始点を知らずにナノ秒)。しかし、それが物事を明確にする場合に備えて、より詳細な答えを突き刺します。

DateTimeDate、およびTimeOfDayは、カレンダーベースの操作用に設計されています。システムクロックとは関係がなく、タイムゾーンの概念もありません。また、日付/時刻の部分を個別の単位 (年、月、日、時間など) として内部的に保持します。したがって、hourフィールドを に設定するDateTimeと、文字通りDateTimeのメンバー変数の 1 つを調整するだけです。そして、Durationそれらに a を追加する場合、それを分割して各ユニットに個別に追加する必要があるためDuration、7 時間の a を追加するなどのことを行うと、フィールドだけでなく増加する可能性がありhourます。例えば

auto dt = DateTime(2015, 8, 2, 20, 0, 0);
dt += hours(7);
assert(dt == DateTime(2015, 8, 3, 3, 0, 0));

また、Durationその値は内部でヘクトナノ秒単位で保持されるため、必ずしも特定の単位に追加する必要はありません。つまり、具体的にフィールド+= hours(7)に追加するようなものではありません。hour全体に数ヘクトナノ秒を追加してDateTimeおり、特定のユニットに影響を与えるのではなく、各ユニットにどのように影響するかを把握する必要があります。例えば

auto dt = DateTime(2015, 8, 2, 20, 0, 0);
dt += hours(7) + minutes(5) + seconds(22);
assert(dt == DateTime(2015, 8, 3, 3, 5, 22));

roll一方、他のユニットに影響を与えずに特定のユニットに追加するためのものです。Adam が正しく判断したように、その主な使用例は、特定の時間単位をある程度調整することになる日付ピッカー ダイアログのスピン コントロールなどであり、他の単位には影響を与えたくないので、あなたは微調整しています。したがって、7 時間を追加すると、1 日が増えるのではなく、時間だけが増えます。

auto dt = DateTime(2015, 8, 2, 20, 0, 0);
dt.roll!"hours"(7);
assert(dt == DateTime(2015, 8, 2, 3, 0, 0));

ここで、月と年は長さが固定されていないため、物事は少し面白くなります。Durationそしてそれが彼らをサポートしない理由です。xヘクトナノ秒がy月やz年に相当するとは言えません。ただし、Duration月または年に関しては意味がありませんが、Dateorに月と年を追加できるようにしたいと考えていますDateTime。そのため、これを処理する必要がadd!"years"ありadd!"months"、1 月 31 日に 1 か月を追加すると、2 月末になるか 3 月初めになるか (2 月 31 日がないため) など、いくつかの奇妙な点を制御できます。

これには、いかなる種類のタイムゾーンも考慮されていません。純粋にカレンダー時間を扱っています。addrollは純粋にカレンダーベースの操作であり、 、 、およびに実装+=されているように、はカレンダーベースの操作です。計算を行う際に、年、月、日などを考慮に入れています (単位はメンバー変数間で分割されているため、この場合は別の方法では実行できません)。DateTimeDateTimeOfDay

そして、私たちは持っていSysTimeます。これは、システムの時刻を表すことを目的としています (これは、タイム ゾーンを考慮に入れることを意味します)。ただし、DST 関連の問題などを回避する唯一の方法は、時刻を常に UTC に保つことです。そのため、SysTime常に内部的に UTC (ヘクトナノ秒単位) で時刻を保持し、TimeZoneオブジェクト (LocalTime既定では) を使用して、必要な場合にのみそれを特定のタイム ゾーンに変換します。これにより、あらゆる種類の厄介な時間関連のバグが回避されます。また、システムの時間で操作している人は、 、、またはSysTimeではなくを使用する必要があります。DateTimeDateTimeOfDay

したがって、SysTimeusingに追加すると、実際にはからのヘクトナノ秒を内部で使用するヘクトナノ+=秒に追加するだけです。カレンダー操作はまったく行われません (もし行われたとしても、多くの DST 関連のバグが発生することになります)。本質的にカレンダーベースではありません。カレンダー操作を行うには、内部で保持されている a のヘクトナノ秒を、グレゴリオ暦の日付で表すものに変換する必要があります (オブジェクトを使用して、タイム ゾーンを考慮します)。DurationSysTimeSysTimeSysTimeTimeZone

ただし、ユーザー フレンドリにするためにSysTime、カレンダー ベースのプロパティと機能の多くを提供しますDateTime(たとえば、、、、yearなどmonthdayプロパティhouraddおよびroll関数)。それをサポートするために、基本的に変換するDateか、DateTime内部的にそれらを実行することになります。これは、タイムゾーンを考慮に入れることを意味し、正しく使用されないと DST バグが発生する可能性があることを意味します。また、場合によっては、厄介なほど非効率的です。たとえば、次のSysTime変数があるとします。st

auto year = st.year;
auto month = st.month;
auto day = st.day;

は 3 回に変換stされますが、明示的に に変換してそこから単位を取得Dateする方が効率的でした。Dateしたがって、その使いやすさは少し両刃の剣です。

また、Adam が DST をどのように追加およびローリング処理するかについて提起した問題も提起されます。rollまたaddSysTime両方とも内部でDateまたはを処理し、UTC から変換するか、UTC からオブジェクトが表すものに変換DateTimeするため、DST が考慮されます。したがって、彼らが操作する方法とまったく同じように操作します。SysTimeDateDateTimeTimeZonerolladdSysTimeDateTimeDateTime

しかし、すでに述べたように、+=onはを UTC 時間にSysTime追加するだけです。そのため、月未満の単位を追加して DST を考慮するDuration方法はありません。SysTime明示的に に変換し、その上DateTimeで使用+=してから に戻す必要がSysTimeありますが、これは少し醜いですが、通常必要なものではありません。月よりも小さい単位で作業を行うことができるとSysTime.add思いますが、そうすると、それを使用している人がいて、DST 関連のバグを使用する必要が+=あるのに、違いを理解していないということになります。

本当に、この時点で、これらのカレンダー機能を に追加することSysTimeが賢明だったのか、実際には意図したように役立つのではなく、最終的にユーザビリティを害しているのか疑問に思います. しかし、現時点でそれを変更できるとは思えません。より正確には、変更することはできますが、これらの機能を非推奨にしSysTime、人々にコードの変更を強制することは、それが引き起こす苦痛に見合う価値があるかどうか疑問に思います. やり直せるなら、カレンダーベースの操作を に置かないことを真剣に検討しSysTimeます。

いずれにせよ、うまくいけば、そのテキストの壁はあなたの時間の価値があるほど十分に啓発的でした.

于 2015-08-02T23:04:10.540 に答える