web-dev-qa-db-ja.com

文字列の日付から年間通算日とユリウス日を抽出する

私はPythonで文字列"2012.11.07"を持っています。それを日付オブジェクトに変換してから、整数値年の日およびユリウス日を取得する必要があります。出来ますか?

22
f.ashouri

まず、次のように datetime.datetime オブジェクトに変換できます。

>>> import datetime
>>> fmt = '%Y.%m.%d'
>>> s = '2012.11.07'
>>> dt = datetime.datetime.strptime(s, fmt)
>>> dt
datetime.datetime(2012, 11, 7, 0, 0)

次に、datetimeのメソッドを使用して必要なものを取得できます。ただし、datetimeには直接必要な関数がないため、 time Tupleに変換する必要があります。

>>> tt = dt.timetuple()
>>> tt.tm_yday
312

「ユリウス日」という用語には、いくつかの異なる意味があります。 2012312を探している場合は、間接的に、たとえば次のいずれかを実行する必要があります。

>>> int('%d%03d' % (tt.tm_year, tt.tm_yday))
2012312
>>> tt.tm_year * 1000 + tt.tm_yday
2012312

別の意味を探しているなら、ここから理解できるはずです。たとえば、「紀元前4713年1月1日からの日数」を意味し、グレゴリオ暦の年と年を必要とする数式がある場合、上記の2つの値を使用してプラグインします。グレゴリオ暦の年、月、日を必要とするので、timetupleステップも必要ありません。)そこからどこへ行くかわからない場合は、詳細を尋ねてください。

数式がない場合(すでに行っている場合でも)、既存のモジュールについてPyPIとActiveStateを調べるのが最善の策です。たとえば、クイック検索では jdcal と呼ばれるものが見つかりました。私はそれを見たことがありませんでしたが、簡単なpip install jdcalとreadmeの短いスキム、そして私はこれを行うことができました:

>>> sum(jdcal.gcal2jd(dt.year, dt.month, dt.day))
2456238.5

これは、USN Julian date converter がくれたのと同じ結果です。

ユリウス日ではなく整数のユリウス日が必要な場合は、丸める方向を決定する必要があります。0に向かって、負の無限大に向かって、正午を翌日に切り上げ、正午を偶数日に丸めますなど(注ユリウス日は、紀元前4713年1月1日の正午から始まると定義されているため、2012年11月7日の半分は2456238、残りの半分は2456239であり、必要なのはどちらかだけです...)

>>> int(sum(jdcal.gcal2jd(dt.year, dt.month, dt.day)))
2456238
45
abarnert

ユリウス日を取得するには、datetime.date.toordinalメソッドを使用して、固定オフセットを追加します。

ユリウス日は、予言的なユリウス暦の紀元前4713年1月1日12時、または 予言的なグレゴリオ暦 の紀元前4714年11月24日12:00以降の日数です。各ユリウス日は、真夜中ではなく正午に始まることに注意してください。

toordinal関数は、予後グレゴリオ暦の紀元前12月31日00:00からの日数を返します(言い換えると、1月1日10:00のADは1日目の始まりです。 0日目)。紀元前1年が紀元1年の直前にあることに注意してください。数0年は数世紀後まで発明されなかったため、年0はありませんでした。

import datetime

datetime.date(1,1,1).toordinal()
# 1

toordinalの結果に1721424.5を追加して、ユリウス日を取得します。

別の回答では、開始した文字列を解析してdatetime.dateオブジェクトに変換する方法について既に説明しました。したがって、次のようにユリウス日を見つけることができます。

import datetime

my_date = datetime.date(2012,11,7)   # time = 00:00:00
my_date.toordinal() + 1721424.5
# 2456238.5
3
ghostarbeiter

Abarnertの答えの最初のステップを単純化するには:

from dateutil import parser
s = '2012.11.07'
dt = parser.parse(s)

次に、残りのabanertの回答を適用します。

3
K.-Michael Aye

この機能(日付文字列からユリウス日付/時刻への変換)も astropy モジュールに存在します。詳細については、 それらのドキュメント を参照してください。アストロピーの実装は、ユリウスdateだけでなく、ユリウスtimeへの簡単な変換に特に便利です。

元の質問のソリューション例:

>>> import astropy.time
>>> import dateutil.parser

>>> dt = dateutil.parser.parse('2012.11.07')
>>> time = astropy.time.Time(dt)
>>> time.jd
2456238.5
>>> int(time.jd)
2456238
3
Kyle

迅速な計算のために、stdlib datetimeモジュールのみを使用して、年間通算日とユリウス日番号を見つけることができます。

_#!/usr/bin/env python3
from datetime import datetime, timedelta

DAY = timedelta(1)
JULIAN_Epoch = datetime(2000, 1, 1, 12) # noon (the Epoch name is unrelated)
J2000_JD = timedelta(2451545) # julian Epoch in julian dates

dt = datetime.strptime("2012.11.07", "%Y.%m.%d") # get datetime object
day_of_year = (dt - datetime(dt.year, 1, 1)) // DAY + 1 # Jan the 1st is day 1
julian_day = (dt.replace(hour=12) - JULIAN_Epoch + J2000_JD) // DAY
print(day_of_year, julian_day)
# 312 2456239
_

_day_of_year_を取得する別の方法:

_import time

day_of_year = time.strptime("2012.11.07", "%Y.%m.%d").tm_yday
_

上記のコードの_julian_day_は "太陽の日に関連付けられたユリウス日番号-開始日に割り当てられたユリウス日番号0から始まる連続した日数の日に割り当てられた番号紀元前4713年1月1日のグリニッジ標準時正午、ジュリアンの予言カレンダー-4712 "

timeモジュールのドキュメント は、用語 "Julian day"を使用します。

Jnユリウス日n(1 <= n <= 365)。うるう日はカウントされないため、すべての年で2月28日は59日目であり、3月1日は60日目です。
n 0から始まるユリウス日(0 <= n <= 365)。うるう日はカウントされ、2月29日を参照することができます。

つまり、ゼロベースのユリウス日はここでは_day_of_year - 1_です。そして、最初のもの(Jn)はday_of_year - (calendar.isleap(dt.year) and day_of_year > 60)です-3月1日から始まる日は、うるう日を除外するためにシフトされます。

関連する用語もあります:ユリウス日付ユリウス日番号は整数です。 ジュリアン日付は本質的に分数です: "(ジュリアン日付(JD)任意の瞬間の前の正午のユリウス日数とその瞬間以降の日の小数部です。 "

一般に、エッジケースを自分で処理しないようにするには、ライブラリを使用してユリウス日を @ abarnertで推奨 として計算します。

2
jfs

この記事 によると、グレゴリオ暦の日付からユリウス暦の日付を計算するために、FliegelとVan Flandernによって作成された未公開の1行の数式があります。

JD = 367 * year - 7 * (year + (month + 9)/12)/4 - 3 * ((year + (month - 9)/7)/100 + 1)/4 + 275 * month/9 + day + 1721029

これは、1900年3月以降にカリフォルニア州パサデナのジェット推進研究所のP. M.ミュラーとR. N.ウィンバリーによって次のように圧縮されました。

JD = 367 * year - 7 * (year + (month + 9)/12)/4 + 275 * month/9 + day + 1721014

これらの式は0.5オフであるため、式から0.5を引くだけです。

文字列の操作を使用して実際にデータを抽出します。

>>> year, month, day = map(int,"2018.11.02".split("."))
>>> 367 * year - 7 * (year + (month + 9)/12)/4 + 275 * month/9 + day + 1721014 - 0.5
2458424.5
0
FGol

上記の例から、ここに1つのライナー(非ジュリアン)があります。

import datetime

doy = datetime.datetime.strptime('2014-01-01', '%Y-%m-%d').timetuple().tm_yday
0
nvd
def JulianDate_to_date(y, jd):
    month = 1
    while jd - calendar.monthrange(y,month)[1] > 0 and month <= 12:
        jd = jd - calendar.monthrange(y,month)[1]
        month += 1
    date = datetime.date(y,month,jd).strftime("%m/%d/%Y")
    return date
0
Mounirsky