std.datetimeの紹介

ジョナサン・M・デイビス著
序文
dmd 2.052で、モジュールが std.datetime導入された。これは、 std.date を完全に置き換えることになる。そのため、std.date は現在 廃止予定となっている。後日、廃止予定となり (その時点で、使用時にコンパイラが警告を発するだけでなく、動作させるには-dでコンパイルする必要がある )、 最終的にはPhobosから完全に削除される。これはつまり、 すべての新しいコードはこれを使用するように書かれるべきであり std.datetime、現在 std.date を使用しているコードはすべて、 を使用するようにリファクタリングする必要がある std.datetime(std.date を自分のコードにコピーして、非Phobosモジュールとして使用し続けることを希望する場合を除く)。本記事では、 について理解を深めていただくことを目的としており std.datetimeまた、std.date からコードを移行する方法についていくつかのアドバイスを std.datetimestd.date を使用している人向けに
。std.date 本質的には、日付と時刻に関するC言語ベースのソリューションである。 は時刻を保持するために使用され、 は64ビットの整数 値であり、UTCにおける1970年1月1日午前0時からの経過ミリ秒数を保持する 。一方、C言語では が時刻を保持するために使用され、 は整数値であり、 UTCにおける1970年1月1日午前0時からの経過秒数を保持する。 そのサイズはアーキテクチャによって異なる (通常は32ビットマシンでは32ビット、64ビットマシンでは64ビットだが、 OSやコンパイラによって異なる)。xml-ph-0000@deepl.internalを使用する際に提供される正確な関数セットは、 での使用に提供される関数の正確なセットは、 での使用に C が提供するものと同じではないが、時間の表現は 事実上同じである。d_time d_time time_t time_t std.date d_time time_t
。 一方、std.datetime一方、Boost.DateTimeは、非常にオブジェクト指向的な ソリューションであり、C言語ベースではない。むしろ、そのAPIは、 Boostの 日付と時刻を処理するための型(ただし、同一ではない)に基づいている。 つまり、std.date からBoost.DateTimeに移行するには、パラダイムシフトが必要だ std.datetime。2つの間で同じ部分が多いとは思わない方が良い。 しかし、 std.datetimestd.date が抱えているようなバグに悩まされることはない (std.date は全般的にかなりバグが多い)。また、std.date よりもはるかに多くの機能を提供している。つまり、 std.datetimeはずである。 ただし、移行には短期的に多少のハードルがあると思われるが。
std.datetimeの基本概念
ほとんどのものはほとんどのものは、 std.datetimeつの概念に基づいており、またそれらを使用しています。
- 期間:単位を持つ時間。例:4日または72 秒。
- 時間:特定の時点。例:21:00 または 2013年5月7日
- 時間間隔:一定の期間。例:[02:44 - 12:22) または [1922年2月4日 - 1955年1月17日 ]。
期間
持続時間の型は、実際には以下で見つけることができる core.time。それらは Durationと TickDuration。 TickDurationは 精密なタイミングを目的としており、主に StopWatch およびベンチマーク関数とともに使用される std.datetime - 。 benchmark - 、それらを使用しない限り、それらを使用することはまずないでしょう。 Duration一方、あなたはかなり使用する可能性が高い。
。 内部では時間をヘクトナノ秒(100 ns)として保持しているため、 これが最大精度となる。 特定の単位に切り捨てられた時間の長さを返すプロパティ関数(Durationヘクトナノ秒(100 ns)として内部的に時間を保持しているため、 これが最大精度となる。 特定の単位に切り捨てられた時間の長さを返すプロパティ関数( days やseconds プロパティ関数など)と、 その単位の総数を返す関数( 関数)の両方がある Duration (total 関数)。
一般的に、 Durationつの方法のうちの1つで作成されます。 2つの時間ポイントを減算するか、または core.time.dur関数を使用して作成される。例えば、 17:02を表す時間ポイントから 6:07を表す時間ポイントを減算すると、 Duration10時間55分を表す 値が得られる。あるいは、 Duration直接作成する場合は、dur 関数を使用し、dur!"hours"(17) またはdur!"seconds"(234) のような呼び出しを行う。
auto duration = TimeOfDay(17, 2) - TimeOfDay(6, 7); assert(duration == dur!"hours"(10) + dur!"minutes"(55)); assert(duration.hours == 10); assert(duration.minutes == 55); assert(duration.total!"hours"() == 10); assert(duration.total!"minutes"() == 655); assert(duration.total!"hnsecs"() == 393_000_000_000);
他の数値と同様に、 Durationそれらを足し合わせたり、そこから引いたりすることができる。ただし、裸の数値とは異なり、それらには単位が 関連付けられており、適切な変換が実行される。 また、druntimeおよびphobosのさまざまな関数で、 Durationむしろ 裸の数値ではなく、実際の数値を取る(ただし、現在では両方を受け付けるバージョンもあるが、 裸の数値を受け付けるバージョンは廃止予定である)。例えば、 core.thread.sleepDuration、 std.concurrency.receiveTimeout。つまり、期間は 単にやりとりする以外の用途にも使用される core.time。 std.datetime。
。 ここで特に注目すべき点は、xml-ph-0000@deepl.internalとxml-ph-0001@deepl.internalの両方が 使用する時間の単位を表す文字列をここで特に注目すべき点は、dur とtotalの両方が、 使用する時間単位を表す文字列を受け取ることである。これは、 全体を通して使用されるイディオムである core.time。 std.datetime。使用可能な 単位は、"years" 、"months" 、"weeks" 、"days" 、 "hours" 、"minutes" 、"seconds" 、"msecs" 、 "usecs" 、"hnsecs" 、"nsecs" である。 ただし、"nsecs" を受け入れる関数はほとんどないことに注意すべきである。なぜなら、 std.datetime、また、ほとんどの関数では core.time、hnsecs(100 ns)よりも大きな精度を持つものは ほとんどない。また、多くの関数( core.time.dur"years" や"months" を受け付けないものもある。 これは、特定の日付なしに年や月をより小さな単位に変換することができないためである。そのため、 Durationある時点に時間を追加することは可能だが、年や月を追加したい場合は、 別の関数(add など)を使用する必要がある。 これらの関数は、"years" と"months"を受け付ける。
時間ポイント
std.datetimeには、時間ポイントを表す4つの型がある。
Aは Date日付を表し、年、月、日を 個別の値として内部的に保持します。A TimeOfDayは、1日のうちの時刻を表し、 00:00:00 - 23:59:59 の範囲で、時、分、秒を個別の値として保持します。 DateTime日付と時刻を表し、 その値は Date。 TimeOfDay。これらの型にはいずれも タイムゾーンの概念はない。これらは一般的な日付および/または時刻を表し 、日付および/または時刻が必要だが、タイムゾーンは気にしない場合に最適である。また、これらの型は 値を内部的に分離して保持するため、値を要求するたびに値を計算する必要はない 。
auto date = Date(1992, 12, 27); auto tod = TimeOfDay(7, 0, 22); auto dateTime = DateTime(1992, 12, 27, 7, 0, 22); assert(date == dateTime.date); assert(tod == dateTime.timeOfDay);
A SysTime、しかし、これはまったく異なるものである。これは 日付と時刻を表すもので、 DateTime - しかし、秒の精度ではなく hnsec の精度で あり、また、 タイムゾーンの概念も組み込まれている。 時刻は内部的に 64 ビットの整数 値として保持されており、これは UTC における紀元 1 年 1 月 1 日の午前 0 時 から経過した hnsec の数を表している。 また、 TimeZoneオブジェクトがあり、 そのオブジェクトは、年や時間などの値を照会する際に、UTC値を適切なタイムゾーンに多様的に調整するために使用される。
。 これは、システムの時計とインターフェースするために使用されるタイプである。 現在の時刻を問い合わせると、SysTimeは、システムの時計とインターフェースする際に使用される型である。 現在の時刻を問い合わせると、 SysTime。 また、常に UTC 形式で内部値を保持しているため、 夏時間やタイムゾーンの変更による問題は発生しない。 DateTimeまた、それ特有の関数も数多く備えている。 他の3つの時間ポイント型に変換することも、それらから構築することも可能だが、 他の3つの時間ポイントから作成する場合は、夏時間に関する問題が発生するリスクがある SysTime他の3つの時間ポイントから作成する場合は、 特に指定しない限り、 SysTime DSTのないものを使用して TimeZoneDSTのないもの(例えば std.datetime.UTC。なぜなら、タイムゾーンに夏時間が適用されている場合、1年間に1時間は存在せず 、別の時間が2回存在することになるからだ。また、 C言語で扱うUnix時間との相互変換も可能である (time_t )。
。この時点で言及しておくべきもう一つの関連型は core.time.FracSec。これは小数秒を保持し、 これは xml-ph-0000@deepl.internal から取得できる Durationまたは SysTime特に 分数部分の時間を要求した場合に
auto st1 = Clock.currTime(); //現地時間での現在時刻。 auto st2 = Clock.currTime(UTC()); //UTCでの現在時刻。 auto st3 = SysTime(DateTime(1992, 12, 27, 7, 0, 22), FracSec.from!"usecs"(5)); assert((cast(Date)st3) == Date(1992, 12, 27)); assert((cast(TimeOfDay)st3) == TimeOfDay(7, 0, 22)); assert((cast(DateTime)st3) == DateTime(1992, 12, 27, 7, 0, 22)); assert(st3.fracSec == FracSec.from!"hnsecs"(50));
時間間隔
std.date 時間間隔に対応するものはないので、 ここでは詳しく説明しない。基本的には、 2つの時間ポイントまたは時間ポイントと期間から構成される。 Interval は2つの終点を持つ有限の時間間隔であるのに対し、 PosInfInterval特定の時点から始まり、正の無限大に向かう無限の時間間隔であり、 NegInfInterval 負の無限大から始まり、特定の時間点に向かう無限の時間間隔である。 これらは交差などを処理するためのさまざまな演算子を持つ。 また、時間点の範囲に対して演算を行いたい場合は、その範囲を作成することも可能である。 詳細はドキュメントを参照してほしい。
C言語とのインターフェイス
うまくいけば、必要なことはすべて、 core.time。 std.datetime。しかし、C言語のコードとインターフェイスする必要がある場合は、 C言語のtime_t は「UNIX時間」( UTCにおける1970年1月1日午前0時からの秒数)を使用するのに対し、 SysTime「std time」と呼ばれるものを使用している(UTCにおける紀元1年1月1日午前0時からの秒数)。 この2つの間の変換は極めて簡単である。 time_t を SysTime、toUnixTime を呼び出すだけでよい SysTime。逆方向の変換を行うには、まずtime_t を標準時(std time)に変換し、その値を SysTimeの コンストラクタに渡す必要がある。また、何らかの理由で単純に SysTime何らかの理由でstdTime プロパティを使用してください。
time_t unixTime = core.stdc.time.time(null); auto stdTime = unixTimeToStdTime(unixTime); auto st = SysTime(stdTime); assert(unixTime == st.toUnixTime()); assert(stdTime == st.stdTime);
ヘクトナノ秒が内部表現として選択されたのは Duration。 SysTime。なぜなら、64ビット整数で使用できる最も高い精度であり、 なおかつ妥当な時間範囲をカバーできるからだ (SysTime紀元前29,000年頃から紀元後29,000年頃までをカバーする)。 また、これはC#が使用する内部表現と同じであるため、何らかの理由でC#とインターフェイスする必要がある場合、 C#の時間表現と std.datetimeの表現に 変換するのは非常に簡単である。なぜなら、変換は必要ないからだ。 C#のDateTime は、内部表現(Ticks と呼ばれている)に同じ単位とエポックを使用している SysTime、 SysTime、負の値(紀元前)には対応しておらず、西暦9,999年を超えることもできない。 しかし、ほとんどのプログラムでは、 その範囲外の値を気にする必要はない。それでも、hnsecsは std.datetime、可能な限り高い精度を追求しようとしている ため、それが選ばれた理由である。
std.datetimeの使用に関する推奨事項
Date、 TimeOfDay、 DateTime、または SysTime特定の状況においてより適切であるかは、その状況に大きく依存する。 Date、 TimeOfDay、 DateTime一般的には、 タイムゾーンとは関係のない一般的な日付や時刻を扱う場合に最も理にかなっている が、タイムゾーンを扱う場合、または夏時間を考慮する必要がある場合は 、 を使用すべきである。 SysTime。なぜなら、内部的には UTC で時間を保持しているため、 夏時間に関する問題を回避できるからだ。また、この関数は時間帯のコンポーネントも保持しているが、 std.datetime.LocalTime(これは システムのローカルタイムのタイムゾーン型である)ので、 通常はタイムゾーンを直接扱う必要はない。
。 もしタイムゾーンを扱いたい場合は、タイムゾーンの種類はタイムゾーンを扱いたい場合は、タイムゾーンの型は std.datetime、 LocalTime、 UTC、 SimpleTimeZone、 PosixTimeZone、 または WindowsTimeZone - あるいは、何らかの理由でそれらがあなたの必要とすることをしない場合、 常に から派生した独自のタイムゾーンクラスを作成することができる TimeZone。 しかし、これは必要ないだろう(もし、 一般的に有用なクラスを思いついた場合は、 digitalmars.Dニュースグループに投稿してほしい。 本当に一般的に有用な場合、そのバージョンを必要とするかもしれない std.datetime。詳細は、そのドキュメントを参照してほしい。ほとんどの アプリケーションでは、タイムゾーンについて心配する必要はないが、 おそらく UTCLocalTime場合によっては
。ある時点の時刻をディスクやデータベース、あるいはそれに類するものに保存する場合は、 一般的にtoISOString またはtoISOExtString 関数を使用することをお勧めする。 どちらも標準の ISO 形式の日付時刻文字列であるためだ (toISOExtString は、より人間にとって読みやすいので、一般的なケースではこちらの方が良いだろう。 しかし、どちらも標準である)。その後、fromISOString またはfromISOExtStringを使用して、 適切な時刻型を再作成することができる。toString は toSimpleString これはBoostの発明であり、 多少は人間にとって読みやすいが、標準ではないため、 おそらく時間を表す値を保存するのには使用すべきではないだろう。
auto dateTime = DateTime(1997, 5, 4, 12, 22, 3); assert(dateTime.toISOString() == "19970504T122203"); assert(dateTime.toISOExtString() == "1997-05-04T12:22:03"); assert(dateTime.toSimpleString() == "1997-May-04 12:22:03"); auto restored = DateTime.fromISOExtString(dateTime.toISOExtString()); assert(dateTime == restored);
時間を文字列として保存する際に少し厄介になる領域として、タイムゾーンがある。 タイムゾーンはISO標準の一部として文字列に含まれるが、 含まれるのは特定の日付と時刻におけるUTCからのオフセットのみであるため、 一般的にISO文字列(拡張文字列またはそれ以外)を使用して、 SysTime 。むしろ、UTCからのオフセットが与えられれば、 SimpleTimeZoneUTCからの指定オフセットで 復元される(UTCの場合を除く。UTCでは復元できる UTC。一方、あなたが LocalTime、タイムゾーンは 文字列の一部ではありません(ISO標準による)。復元すると、 SysTime、その文字列は、そのボックスの現在のタイムゾーンに復元される。 元のタイムゾーンが何であったかに関係なく。ただし、 LocalTime、UTCオフセットは文字列に含まれているため、 通常は、正確なUTC時間を取得することが可能である SysTime。しかし、通常は、ISO 文字列から元のタイムゾーンを復元することはできない。
auto local = SysTime(629_983_705_230_000_035); auto utc = local.toUTC(); auto other = local.toOtherTZ(TimeZone.getTimeZone("America/New_York")); //これは、あなたが"America/Los_Angeles"にいると仮定している。別のタイムゾーンにいる場合は //異なる時刻が表示される。 assert(local.toISOExtString() == "1997-05-04T12:22:03.0000035"); assert(utc.toISOExtString() == "1997-05-04T19:22:03.0000035Z"); assert(other.toISOExtString() == "1997-05-04T15:22:03.0000035-04:00"); auto restLocal = SysTime.fromISOExtString(local.toISOExtString()); auto restUTC = SysTime.fromISOExtString(utc.toISOExtString()); auto restOther = SysTime.fromISOExtString(other.toISOExtString()); //同じマシン上だから保証される。 assert(restLocal == local); //マシンに関係なく保証される。ただし、内部的な値は異なる可能性がある。 assert(cast(DateTime)restLocal == cast(DateTime)local); //タイムゾーンはどちらもUTCである。 assert(restUTC == utc); //restOtherのタイムゾーンはSimpleTimeZone(-4 * 60)であり、"America/New_York"ではない。 assert(restOther == other);。
まとめると、 UTC、 SimpleTimeZoneISO または ISO 拡張文字列を使用すれば、正確に復元できる。 しかし、他のどれもが TimeZoneできない。 LocalTimeは、同じ日付と時刻で復元されるが、 復元先のコンピュータのローカルタイムゾーンで復元されるため、標準時刻は異なる可能性がある。 他のタイムゾーンでは、復元された SysTime元のタイムゾーンと同じ標準時になるが、新しいタイムゾーンは SimpleTimeZone 元のタイムゾーンが指定された標準時において持っていたのと同じ UTC オフセットの合計を持つことになるが、 元のタイムゾーンは戻らない。 その値を変更する必要がなく、 SysTime、または元のタイムゾーンの名前を知る必要がない場合は問題ありませんが、 いずれかが必要な場合は不適切です。なぜなら、 新しいタイムゾーンのルールは元のタイムゾーンのルールと一致しないからです。
。そのため、タイムゾーンを気にしていない場合や、復元した SysTime オリジナルと同じ標準時である場合は、 LocalTime問題ありません。 しかし、標準時を統一したい場合は、 LocalTime。ほとんどの場合、単純に UTCタイムゾーンとして 時刻を保存することをお勧めする。また、タイムゾーンを 保存前のものと同じタイムゾーンで同じルールで復元したい場合は、 その情報を自分で保存する必要がある。 PosixTimeZoneまたは WindowsTimeZone、必要なのは タイムゾーンのname を保存することだけです(それぞれ、TZデータベース名と そのタイムゾーンのWindowsタイムゾーン名です)。これは タイムゾーンを復元する際に使用できます。それが SimpleTimeZoneまたは UTC、 ISO 文字列で十分なので、何もする必要はありません。 もし LocalTime、しかし、少し厄介なことになります。
復元されたタイムゾーンは LocalTimeので、 復元作業を行っているコンピュータのローカルタイムであれば、 問題ない。しかし、コンピュータのローカルタイムに関係なく、同じ実際のタイムゾーンを復元したい場合は、 復元するコンピュータのタイムゾーンのTZ データベース名またはWindowsタイムゾーン名を把握する必要がある。 そうすれば、 PosixTimeZone、 WindowsTimeZone 復元を行うコンピュータ上で対応するものを使用できるようにする必要がある。しかし、 Windows以外のOSでローカルタイムゾーンのTZデータベース名またはWindows タイムゾーン名を正確に決定するのは非常に難しいstd.datetime現時点では、そのための手段は提供していない。 しかし、そのような要件はかなり稀であると予想している。ほとんどの場合、 あなたは LocalTime、あるいは UTC、また、たとえ PosixTimeZoneまたは WindowsTimeZone、正しい標準時値と正しい UTC オフセットで時間を復元すれば十分である可能性が高い (それでも不十分な場合は、いつでもタイムゾーンの名前を保存して 正しい PosixTimeZone。 WindowsTimeZone。ただ、 LocalTime問題があるのは それだけだ。しかし、もし正確にローカルタイムゾーンの TZ データベース名を決定する関数が Posix システム上で考案された場合、 その関数は追加されるだろう std.datetime。
よりコンパクトな保存方法としては、 SysTime、単に 標準時を64ビット整数として保存するという方法もある。これは、ISOやISO拡張文字列のように人間が読めるものではないが 、文字列ではなく実際の数値として保存すれば、より少ないスペースで済む 。ただし、この方法では、 タイムゾーンを復元したい場合は、完全に自分で管理しなければならない。しかし、現在のUTCオフセット(つまり、 つまり、夏時間オフセットが適用された UTC オフセットを意味する - ISO 文字列には 含まれる)を保存すれば、元のタイムゾーンを復元できなくても、 そのタイムゾーンにおける本来の時刻を正しく示すのに十分である 。
。まあ、タイムゾーンについてはこれで十分すぎるほどだ。ほとんどの場合、 タイムゾーンについて気にする必要はない(SysTimeそう設計されているので 、必要なければ気にする必要はない)、 しかし、 std.datetime実際にタイムゾーンを扱う必要が生じた際に、最良のツールを提供できるよう努めている。 いずれにしても、 SysTime、内部時刻は常に UTC であるという点です。 そのため、タイムゾーンを明示的に扱うかどうかに関わらず、 DST の変更を扱う際に問題が発生することはありません。 SysTime。
。最後に、使用上のアドバイスをもうひとつ。 SysTime。 複数のプロパティ(例えば、day またはhour )について問い合わせる必要がある場合、または、何度も連続して問い合わせる必要があり、 SysTime変更されない場合は、おそらく別の時間ポイント型(おそらく DateTimeそれらの値を問い合わせるために、別の時間ポイント型にキャストした方が良いでしょう。 この理由は、プロパティ関数を呼び出すたびに SysTime、内部の std 時間を あなたが要求しているプロパティの値に変換しなければなりません。一方、 それを DateTime、 DateTimeそれらの値は別々に保持され、 計算は一度だけ行うだけで済む。 から SysTimeから DateTime。もしあなたがやっていることが その余分な効率化を必要としないのであれば、 わざわざ変換する必要はないかもしれないが、 それぞれのプロパティを個別にクエリするよりも SysTime。プロパティを個別にクエリするよりも、 それを変換して DateTimeし、それを照会する方が効率的です。
auto st = Clock.currTime(); //それぞれの値は個別に計算する必要がある。 { auto year = st.year; auto month = st.month; auto day = st.day; auto hour = st.hour; auto minute = st.minute; auto second = st.second; auto fracSec = st.fracSec; } /+ DateTimeに変換する場合、計算を2回行うだけだ (1回ではなく2回、なぜならまだFracSecを 別に求めているからだ、その計算はかなり安いが)。 +/ auto dateTime = cast(DateTime)st; { auto year = dateTime.year; auto month = dateTime.month; auto day = dateTime.day; auto hour = dateTime.hour; auto minute = dateTime.minute; auto second = dateTime.second; auto fracSec = st.fracSec; }
std.datetimeへの移行
よし、うまくいけば、基本的なことは大体理解できたはずだ。さて、この時点で基本的なことは大体理解できていると思うが std.datetime (ドキュメントには他にも多くの内容が記載されているが)。しかし、多くの人にとっての大きな問題は、std.date を使用しているコードをどのように変換するのが最善かということだ std.datetime。std.date を使用している場合、d_time を使用していることになり、 タイムゾーンを考慮する必要がある場合は、おそらく C 関数を使用して変換を処理するか、またはご自身で変換処理を行っていたことだろう。 なぜなら、std.date のタイムゾーンに関連する機能は、 かなり不完全だからだ。その結果、おそらくほとんどの処理は UTC で行われていることだろう。
。 xml-ph-0000@deepl.internal と同様に、内部的に UTC を使用して時間を保持している (単位とエポックは異なるが)。 これは、時間を扱うために意図されたタイプである。SysTimeは、d_time と同様に、内部的には UTC で時間を保持している(単位とエポックは異なるが)。 また、 これはシステムの時計からの時間処理を目的とした型であるため、 SysTime通常は、d_time を置き換える対象となるものです。 Phobos で以前はd_time を取得または返却していた関数は、現在では を取得または返却する SysTime廃止予定となり、 xml-ph-0001@deepl.internal を受け取るか返す代替の関数が用意される SysTime。一般的に、d_time を引数にとる関数の場合は、その関数は を引数にとるバージョンでオーバーロードされる SysTime。しかし、 関数をオーバーロードできない場合(単純にd_time を返す場合など )、古い関数を置き換える新しい関数が追加されている( そのため、既存のコードが壊れることはない)。この変更の影響を最も受けるモジュールは std.file。例えば、
d_time dTime = "myfile.txt".lastModified(); SysTime sysTime = "myfile.txt".timeLastModified(); setTimes("yourfile.txt", dTime, dTime + 5); setTimes("yourfile.txt", sysTime, sysTime + dur!"msecs"(5));
このような関数のすべてにおいて、単に問題となるのは、 関数に渡す引数の型を変更するか、その 戻り値を代入するか、場合によっては呼び出す関数名を変更して SysTime。これらの 変更は極めて単純であり、特に混乱を招くものではない。 それよりも、時間が表示または保存されるフォーマットや、 タイムゾーンの処理方法の方が懸念される。
もしあなたがどこかにd_time の値を保存しているのなら、 以前に説明したように、値を保存する際に使用する SysTime以前に説明したように使用する値(例えば、その標準時間やISO文字列)を保存するように切り替えるか、 またはd_time と SysTime。現時点では、 std.datetime.sysTimeToDTimeと std.datetime.dTimeToSysTimeこれらの変換を自動的に行ってくれる。 そのため、2つのフォーマット間の変換は簡単だ。しかし、d_time が廃止されるため、これらの関数も廃止されることになる。 つまり、これらの関数が必要なくなるようにコードを書き換えるか、 それらの関数を自分のコードにコピーして、引き続きそれらを使用する必要がある
。フォーマット済みの文字列に関しては、 std.datetime現在は、 ISO 文字列、ISO 拡張文字列、Boost の単純文字列のみをサポートしている。 将来的には、カスタム文字列用の関数も必要になるだろうが、 フォーマット文字列を基にカスタム文字列を作成する std.datetime(私のToDoリストには載っているが、着手するにはまだしばらく時間がかかりそうだ)。 そのため、一般的には、 サポートされている文字列フォーマットのいずれかに切り替えるか、 std.datetime サポートする文字列フォーマットに切り替えるか、 自分で希望する文字列フォーマットを生成して解析する必要がある。場合によっては、core.stdc.time.ctime が返す文字列を調整できるはずであり、 また、toISOExtString を使用して返される文字列を調整できる場合もあるが、 さまざまなプロパティを使用して文字列を自分で作成して解析しなければならない可能性も十分にある SysTime。std.date の文字列関数と それらの主な違いとして、 std.datetime"注釈:" std.date とは異なり、Boostのシンプルな文字列を除いて、 std.datetime月名や曜日名を表示するものは何もありません。なぜなら、 それはローカライゼーションの問題を引き起こすからです。そのため、 core.stdc.time.ctime を使用してそれらの値を取得しない限り、 それらの名前は自分で作成する必要があります。
。std.date を使用してタイムゾーンに関する処理を行なっていた場合、 おそらくそれらの変換をすべてご自身で行なっていたことだろう( std.date はバグが多い分野のひとつであるため)。その場合、 おそらく UTC からのオフセットと、 対象のタイムゾーンの夏時間調整値をお持ちだろう。 それらを使用して作成するのが、おそらく最善の方法である。 SimpleTimeZoneそれらの値を使用して作成する。 単純に、UTCオフセットの合計(該当する日付に夏時間オフセットが適用される場合は、それを加算する)を分単位で計算し、 SimpleTimeZone 。 std.datetimeUTCより西側は 負の値として扱われる(いくつかの理由により、一部のシステム(特にPosix系)では、 UTCより西側にある場合、UTCからの正のオフセットを使用しているが、 タイムゾーンについて話す際には、UTCより西側にある場合は常に負の値が使用される。 そのため、 値を適宜調整する必要があるかもしれない。いずれにしても、 自分が使用している値が時間単位で何を意味しているのかを理解していることを確認し、 UTCからのオフセットに変換するためにそれらの値を加算または減算する必要があるかどうかを SimpleTimeZoneUTCからのオフセットとして期待されるものに変換する必要があるかどうかを 確認してください。UTCの時刻に何分足せば 目標のタイムゾーンの時刻になるか、という
//これらはAmerica/Los_Angelesと同じオフセットである。 auto utcOffset = -8 * 60; auto dstOffset = 60; immutable tzWithDST = new SimpleTimeZone(utcOffset + dstOffset); immutable tzWithoutDST = new SimpleTimeZone(utcOffset);。
最後に、std.date と の数値に若干の違いがあることを注釈しておく。 std.datetime。std.date.Date のweekday プロパティでは、日曜日の値が 1となっているが、std.date.weekDay では日曜日の値が0となっている。 std.datetime.DayOfWeekは日曜日に0の値を与える。つまり、std.date のどの部分を扱っているかによって、 std.datetime平日の数値に対して行っている処理と一致する 場合と一致しない場合がある。月についても同様の問題がある。std.date.Date のmonth プロパティは1月に値1を与えている が、これは std.datetime.Monthしかし、std.date.monthFromTime は1月に0の値を与えている。つまり、 曜日と同様に、月の数値にも注意が必要だ。 std.datetimestd.date が実行している内容と一致するかどうかは、std.date のどの部分を使用しているかによって異なる。 また、お気づきのように、std.date.Date とstd.date の無料関数のどちらが一致するのかについても一貫していない std.datetime。そのため、 曜日または月を表す数値を使用するコードを変換する際には、 十分に注意する必要がある。
。std.date | std.datetime 同等 |
d_time | 最も近いものは、次のとおりである。 SysTime。 |
d_time_nan | 同等のものはない。 SysTime。init は、null という TimeZoneオブジェクトを持つものが最も近いでしょうが、 一度CTFEがクラスオブジェクトを新規作成できるほど進歩すれば、 SysTime。init のtimezone は LocalTimeので、xml-ph-0000@deepl.internal が SysTime。init が 無効であることは std.datetime一般的に、 どの型についても無効な状態を発生させないように努めている。 そのような値を作成することは不可能であるように意図されている。 |
Date | SysTime |
Date。year | SysTime。year |
Date。month | SysTime。month |
Date。day | SysTime。day |
Date。hour | SysTime。hour |
Date。minute | SysTime。minute |
Date。second | SysTime。second |
Date。ms | SysTime。fracSec.msecs |
Date.weekday | SysTimedayOfWeek - ただし、"値"は1ずれていることに注意 してほしい。 |
Date。tzcorrection | immutable tz = sysTime.timezone; auto diff = tz.utcToTZ(sysTime.stdTime) - sysTime.stdTime; auto tzcorrection = convert!("hnsecs", "minutes")(diff);ただし、tzcorrection が壊れているようなので、 いずれにしてもコードでは使用しない方が良いだろう。 |
Date。parse | SysTime。fromISOString 、 SysTime。fromISOExtString 、 SysTimefromSimpleString だが、文字列のフォーマットはstd.date.Date が受け付けるものと異なる。parse が受け付けるものとも異なる。 |
ticksPerSecond | 同等のものはない。d_time に関連するものだけだ。 |
toISO8601YearWeek | SysTime。isoWeek |
hourFromTime | SysTime。hour |
minFromTime | SysTime。minute |
secFromTime | SysTime。second |
daysInYear | sysTime.isLeapYear ? 366 : 365 |
dayFromYear | (sysTime - SysTime(Date(1970, 1, 1), UTC())).total!"days"() |
yearFromTime | SysTime。year |
inLeapYear | SysTime。isLeapYear |
monthFromTime | SysTimemonth - ただし、値が1ずれていることに注意 してほしい。 |
dateFromTime | SysTime。day |
weekDay | SysTime。dayOfWeek |
UTCtoLocalTime | SysTime。toUTC |
dateFromNthWeekdayOfMonth | //同等のものはない。これは可能な実装である。 int dateFromNthWeekdayOfMonth(int year, Month month, DayOfWeek dow, int n) { auto first = Date(year, month, 1); auto target = first; immutable targetDOTW = target.dayOfWeek; if (targetDOTW != dow) { if (targetDOTW < dow) target += dur!"days"(dow - targetDOTW); else { target += dur!"days"((DayOfWeek.sat - targetDOTW) + dow + 1); } } target += dur!"weeks"(n - 1); if (target.month != first.month) target -= dur!"weeks"(1); return cast(int)((target - first).total!"days"()) + 1; } |
daysInMonth | SysTime。endOfMonthDay; 実際、この名前は endOfMonth と混同しやすい。 は SysTime。おそらくdaysInMonth に変更するだろう。しかし、変更するとしても、 次のリリース(2.054)まで先になるだろう。この名前は 廃止サイクルが完全に終了するまで残るだろう。 |
UTCtoString | 同等のものはない。おそらく、core.stdc.time.ctime と SysTime。toISOExtString を解析して再結合し、 を作成することはできるだろう。しかし、 そもそもこの関数はかなりバグが多いように見えるので、 あなたのコードでは使用していない可能性が高い。 |
toUTCString | 同等のものはない。おそらく、core.stdc.time.ctime を解析して再結合できるだろう。 SysTime。toISOExtString を解析して作成することはできるだろう。 |
toDateString | 同等なものはない。おそらく、core.stdc.time.ctime と を解析して再結合し、 SysTime。toISOExtString を使って作成することはできる。しかし、 この関数はそもそもかなりバグが多いように見える。 そのため、あなたのコードがこの関数を使用していない可能性が高い。 |
toTimeString | 同等のものはない。おそらく、core.stdc.time.ctime を解析して再結合することは可能だろう。 SysTime。toISOExtString を解析して再結合し、 を作成することはできるだろう。しかし、 この関数はそもそもかなりバグが多いように見えるので、 |
parse。parse | SysTime。fromISOString 、 SysTime。fromISOExtString 、 SysTimefromSimpleString だが、文字列のフォーマットがstd.date.parse が受け付けるものと異なる。 |
getUTCtime | Clock.currTime(UTC()) もしあなたが SysTimeタイムゾーンを UTC。しかし、おそらくは、Clock.currTime() を使用するだけだろう。内部時間はUTCで ある。 |
DosFileTime | DosFileTime |
toDtime | DosFileTimeToSysTime |
toDosFileTime | SysTimeToDosFileTime |
benchmark | benchmark |
私はstd.date で動作するもの、しないものの専門家ではないことに注意してほしい。 私が動作しないと知っている関数のいくつかを指摘したとしても、 上の表で動作しないと表示されていないからといって、その関数が正しく動作するとは限らない。そして、 正しく動作しない関数は、当然ながら、 std.datetime。なぜなら、 std.datetimeバージョンにはバグがないことはほぼ確実であり、同じバグがあるとしても(もしバグがあるとしても、そのバグはstd.date のバグよりもはるかに微妙なものになる可能性が高い std.datetime徹底的に ユニットテストされているため)
結論結論
この記事が、皆さんの理解を深めるのに役立ったことを願って std.datetime、そして、std.date からコードを移行できるようになるための道筋をしっかりとつかんでいただけたことでしょう std.datetime。 さらにご質問がある場合は、digitalmars.D.learnニュースグループまでお問い合わせください。 また、std.date の主要な使用事例で、 std.datetimeこの記事で取り上げ損ねたが、 取り上げるべきだと考える場合は、digitalmars.Dニュースグループで 遠慮なく話題にしてほしい。必要であれば、関連情報をこの記事に追加する。
DEEPL APIにより翻訳、ところどころ修正。
このページの最新版(英語)
このページの原文(英語)
翻訳時のdmdのバージョン: 2.109.1
ドキュメントのdmdのバージョン: 2.109.1
翻訳日付 :
HTML生成日時:
編集者: dokutoku