Julian datesをC++で処理する最良の方法は?私は、ユリウス暦の日付とグレゴリオ暦の日付の間で変換できるようにしたい。私はC++ 11とC++ 14を持っています。 <chrono>
ライブラリでこの問題を解決できますか?C++でユリウス日付を扱う方法11/14
答えて
Julian dateとstd::chrono::system_clock::time_point
の間で変換するには、まず最初にエポックの違いを調べる必要があります。
system_clock
には公式エポックはありませんが、事実上の標準エポックは1970-01-01 00:00:00 UTC(グレゴリオ暦)です。便宜上、proleptic Gregorian calendarの点でJulian dateエポックを記述すると便利です。このカレンダーは、現在のルールを後方に拡張し、年0を含みます。これは算術を簡単にしますが、1を減算して無効にすることでBC年を負の年に変換する必要があります(2BCは年-1など)。 Julian dateエポックは、-4713-11-24 12:00:00 UTC(おおよそのこと)です。
<chrono>
ライブラリは、このスケールで時間単位を扱うのに便利です。さらに、this date libraryは、グレゴリオ暦の日付とsystem_clock::time_point
との間の変換に便利です。これら二つのエポックの差を検索するには、単純です:
constexpr
auto
jdiff()
{
using namespace date;
using namespace std::chrono_literals;
return sys_days{jan/1/1970} - (sys_days{nov/24/-4713} + 12h);
}
これは時間の周期でstd::chrono::duration
を返します。 C++ 14では、これはconstexpr
となり、std::chrono::hours{12}
ではなく、クロノ継続時間リテラル12h
を使用できます。
あなたはdate libraryを使用したくない場合は、これは時間のちょうど一定の数であり、この多くの不可解な形に書き換えることができます。
constexpr
auto
jdiff()
{
using namespace std::chrono_literals;
return 58574100h;
}
あなたはそれを書くいずれかの方法で、効率が同じです。これは、定数58574100
を返す関数に過ぎません。これはまたconstexpr
グローバルかもしれませんが、使用する宣言を漏らしたり、それらを使用しないことを決めなければなりません。
次は、ユリウス日時計(jdate_clock
)を作成すると便利です。私たちは少なくとも半日ほどの単位で対処する必要があり、ユリウス日を浮動小数点日として表現するのが一般的ですから、jdate_clock::time_point
はエポックから2倍の日数をカウントします:
struct jdate_clock
{
using rep = double;
using period = std::ratio<86400>;
using duration = std::chrono::duration<rep, period>;
using time_point = std::chrono::time_point<jdate_clock>;
static constexpr bool is_steady = false;
static time_point now() noexcept
{
using namespace std::chrono;
return time_point{duration{system_clock::now().time_since_epoch()} + jdiff()};
}
};
実装上の注意:
私は
system_clock::duration
はナノ秒であるそれらのシステムのためのオーバーフローを避けるために、すぐにsystem_clock::now()
からduration
への復帰を変換します。
jdate_clock
は完全に適合し、完全に機能するクロックである<chrono>
になりました。これは、そのjdate_clock::time_point
でタイプセーフなシステムであり、system_clock::time_point
はどちらができる2つの別個のタイプです
2457354.310832
:これだけの出力
std::cout << std::fixed;
std::cout << jdate_clock::now().time_since_epoch().count() << '\n';
:たとえば、私はそれをして、今あるものを時間を見つけることができます誤って混在算術を実行することはありません。それでも、jdate_clock::time_point
への/からの継続時間の加算や減算など、<chrono>
ライブラリの豊富な利点をすべて引き続き得ることができます。
using namespace std::chrono_literals;
auto jnow = jdate_clock::now();
auto jpm = jnow + 1min;
auto jph = jnow + 1h;
auto tomorrow = jnow + 24h;
auto diff = tomorrow - jnow;
assert(diff == 24h);
しかし、私は誤って言った場合:
auto tomorrow = system_clock::now() + 24h;
auto diff = tomorrow - jnow;
私はこのようなエラーが出るでしょう:英語で
error: invalid operands to binary expression
('std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<long long,
std::ratio<1, 1000000> > >' and 'std::chrono::time_point<jdate_clock, std::chrono::duration<double,
std::ratio<86400, 1> > >')
auto diff = tomorrow - jnow;
~~~~~~~~^~~~~
を:あなたはstd::chrono::system_clock::time_point
からjdate_clock::time_point
を減算することはできません。
しかし、時には私がはjdate_clock::time_point
system_clock::time_point
にまたはその逆に変換します。
template <class Duration>
constexpr
auto
sys_to_jdate(std::chrono::time_point<std::chrono::system_clock, Duration> tp) noexcept
{
using namespace std::chrono;
static_assert(jdate_clock::duration{jdiff()} < Duration::max(),
"Overflow in sys_to_jdate");
const auto d = tp.time_since_epoch() + jdiff();
return time_point<jdate_clock, decltype(d)>{d};
}
template <class Duration>
constexpr
auto
jdate_to_sys(std::chrono::time_point<jdate_clock, Duration> tp) noexcept
{
using namespace std::chrono;
static_assert(jdate_clock::duration{-jdiff()} > Duration::min(),
"Overflow in jdate_to_sys");
const auto d = tp.time_since_epoch() - jdiff();
return time_point<system_clock, decltype(d)>{d};
}
実装上の注意:1つは簡単にヘルパー関数のカップルを書くことができますについて
私はあなたがナノ秒または32ビットベースの分を使用した場合に発生する可能性がある静的な範囲チェックを追加しましたあなたのソースの期間として
time_point
。
一般的なレシピは、エポックduration
を得ることである(duration
sは「クロックニュートラル」)、追加またはエポックの間のオフセットを減算し、次に所望time_point
にduration
を変換します。
これらは、すべてのタイプセーフな方法で、にどんな精度を使用して、2つのクロックのtime_point
sの間で変換します。それがコンパイルされていれば動作します。プログラミングエラーが発生した場合は、コンパイル時に表示されます。有効な例の用途は、次のとおりです
auto tp = sys_to_jdate(system_clock::now());
tp
は、それが何であれ、あなたのsystem_clock::duration
の精度で積分表示を持っていることを除いてjdate::time_point
です(私にとってはそれがマイクロ秒である)です。それがナノ秒(gcc)の場合、ナノ秒は+/- 292年の範囲しかないので、これはオーバーフローすることに注意してください。
あなたはそうのような精度を強制することができます。
auto tp = sys_to_jdate(time_point_cast<hours>(system_clock::now()));
そして今tp
はjdate
エポックからの時間の整数カウントです。
this date libraryを使用したい場合は、上のユーティリティを使用して、浮動小数点ジュリアン日付をグレゴリオ暦の日付に簡単に変換できます。たとえば:
using namespace std::chrono;
using namespace date;
std::cout << std::fixed;
auto jtp = jdate_clock::time_point{jdate_clock::duration{2457354.310832}};
auto tp = floor<seconds>(jdate_to_sys(jtp));
std::cout << "Julian date " << jtp.time_since_epoch().count()
<< " is " << tp << " UTC\n";
我々はjdate_clock::time_point
を作成するために、私たちのjdate_clock
を使用しています。次にjdate_to_sys
変換関数を使用してjtp
をsystem_clock::time_point
に変換します。これには、倍数と時間の表現があります。それは本当に重要ではありません。どのような重要ですどのような表現と精度に変換することですが必要です。私はfloor<seconds>
でこれを行いました。私もtime_point_cast<seconds>
を使っていた可能性があり、同じことをしていたでしょう。 floor
はthe date libraryに由来し、常に負の無限大に切り詰められ、綴りが容易です。
この意志出力:私ではなく、床の最も近い秒に丸めたい場合
Julian date 2457354.310832 is 2015-11-27 19:27:35 UTC
、それは単純に次のようになります。
auto tp = round<seconds>(jdate_to_sys(jtp));
Julian date 2457354.310832 is 2015-11-27 19:27:36 UTC
それとも私が最も近いミリ秒にそれを望んでいた場合:
auto tp = round<milliseconds>(jdate_to_sys(jtp));
Julian date 2457354.310832 is 2015-11-27 19:27:35.885 UTC
更新
Howard Hinnant's date libraryの一部として前述のfloor
とround
の関数は、C++ 17の一部としてネームスペースstd::chrono
でも利用できるようになりました。
- 1. YYYY-MM-DD Pythonのユリウス日の日付
- 2. r - data.tableでユリウス日付をカレンダー日付に変換する
- 3. XSLT - 日付(YYYY-MM-DD)をユリウス日に変換する
- 4. Djangoで日付を扱うには?
- 5. Linqクエリで日付を扱うには?
- 6. 日付範囲内でNULL日付を扱う
- 7. はXSLTでユリウス日付を比較して、高い
- 8. 年のない日付をユリウス暦の日付に変換します。
- 9. C:ユリウス日ライブラリー - 日付オフセット(Xからの日数)から日付(つまり、yyyy/mm/dd)を取得するにはどうすればよいですか?
- 10. 恐ろしい日付データを扱うデータを扱う
- 11. bash - ユリウス日を取得する方法(現在)?
- 12. SQL Server/Oracle Linked - ユリウス日エラー
- 13. boost :: gregorian :: date.day_number()はユリウスの日付を返します
- 14. Fとの日付を扱う#
- 15. d3.js軸の日付を扱う
- 16. 文字列/日付アトリビュートの扱い方
- 17. スカラで現在のユリウス暦の日付を取得し、それを通常の日付に変更します
- 18. 現在の日付をユリウス日時に変換するにはどうすればよいですか
- 19. ggplot2はクラス日付のデータを扱う方法を知らない
- 20. JCL-SYNCSORTを使ってPDジュリアンの日付と(現在のユリウスの日付-7)を比較するには?
- 21. XSLどのように特定の日付のユリウス日を見つけるには?
- 22. 抽出日月ユリウス日時から、Pythonで
- 23. Pythonで日付を扱うcsvファイルを読み書きする
- 24. 〜をファイルパスで扱う方法
- 25. ペンタホケトルでの日付の扱い
- 26. Hibernateでゼロの日付( "0000-00-00")を扱うには?
- 27. Zend_Dateで日付と時間帯を扱う
- 28. Reactで条件付きスタイルを扱う正しい方法
- 29. フィットネスデテーブルセルから今日の日付をC#フィクスチャに渡す方法
- 30. Angular2日付フィルタC#日付?
+1に質問してください。私はスポンサーシップのいくつかの特徴を私に思い出させるので、答えはしていない。あなたが純粋なC++バージョンを提供しているという事実は、平均格付けをも引き上げています。ただ私の客観的な見解です。 – edmz
@black:問題ありません。 Fwiw、日付ライブラリ(スポンサーシップ)は無料のオープンソース、MITライセンス、githubリポジトリです。次に、日付ライブラリが基づいているパブリックドメインアルゴリズムhttp://howardhinnant.github.io/date_algorithms.html(独自の日付ライブラリを作成する場合)を示します。 –