将 python 日期时间对象格式化为参数
Formatting python datetime object as argument
对 python 有点陌生,但试图将其用于卫星轨道分析。我真的没有得到日期时间对象和方法。我希望能够将 datetime 对象传递给一个函数,该函数接受与 datetime 格式基本相同的参数(年、周一、日、小时、分钟、秒)。下面的代码有效,但 has 是更好的方法。请赐教。谢谢!
import jday
import datetime
jdate = jday.JD(2015,12,1,22,8,0) # example
now1 = datetime.datetime.now().strftime("%Y,%m,%d,%H,%M,%S")
now2 = now1.split(",")
now3 = [int(i) for i in now2]
jdatenow = jday.JD(*now3)
print jdatenow
jday 模块是从 David Vallado 的 Astrodynamics 源代码的 Matlab 移植过来的。
import math as m
def JD(yr, mon, day, hr, min, sec):
jd = 367.0 * yr - m.floor(
(7 * (yr + m.floor( (mon + 9) / 12.0) ) ) * 0.25 ) + m.floor(
275 * mon / 9.0 ) + day + 1721013.5 + (
(sec/60.0 + min ) / 60.0 + hr ) / 24.0
return jd
我能想到的最短路径:
now = list(datetime.datetime.now().timetuple())[:-3]
遗憾的是,您不能将日期时间对象直接传递给需要整数的函数。您是否有任何特殊原因无法使用 datetime 提供的字段调用该函数?
now = datetime.now()
jdatenow = jday.JD(now.year, now.month, now.day, now.hour, now.minute, now.second)
或者如果这太麻烦了,把它包起来:
from datetime import datetime
def my_JD(dt):
return jday.JD(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)
jdatenow = my_JD(datetime.now())
这可能比
更容易理解
jdatenow = jday.JD(*list(datetime.now().timetuple())[:-3])
鉴于您已经移植了 JD 代码,因此可以将其作为模块 jday 进行控制,也许装饰器就是您想要的正在找。这样做的明显好处是不会破坏函数的原始签名(对于现有的客户端代码),但会根据您的要求增加日期参数的便利性。
还创建了一个 jday2 模块,它与原始 jday 模块相同,但其 JD() 函数改为直接接受日期对象。如果您不需要任何向后兼容性,这是最简单的解决方案。
请参阅下面的工作示例代码:
jday.py
import math as m
import functools
def date_support_wrapper(f):
""" Wraps JD and provides a way to pass a date param
:param f: the original function
:return: the wrapper around the original function
"""
@functools.wraps(f)
def wrap(*args, **kwargs):
if 'date' in kwargs:
d = kwargs['date']
return f(yr=d.year, mon=d.month, day=d.day, hr=d.hour, min=d.minute, sec=d.second)
return f(*args, **kwargs)
return wrap
@date_support_wrapper
def JD(yr, mon, day, hr, min, sec):
jd = 367.0 * yr - m.floor(
(7 * (yr + m.floor((mon + 9) / 12.0))) * 0.25) + m.floor(
275 * mon / 9.0) + day + 1721013.5 + (
(sec / 60.0 + min) / 60.0 + hr) / 24.0
return jd
jday2.py
import math as m
def JD(dt):
""" Same calculation as JD but accepts a date object argument
:param dt: the date object
:return: the JD result
"""
yr, mon, day, hr, min, sec = dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second
jd = 367.0 * yr - m.floor(
(7 * (yr + m.floor((mon + 9) / 12.0))) * 0.25) + m.floor(
275 * mon / 9.0) + day + 1721013.5 + (
(sec / 60.0 + min) / 60.0 + hr) / 24.0
return jd
以及示例客户端代码:
client.py
import datetime
import jday
import jday2
# The date we are interested in
a = dict(year=2015, month=12, day=1, hour=22, minute=8, second=0)
dt = datetime.datetime(**a) # 2015-12-01 22:08:00
# The original signature of the function
jdate1 = jday.JD(a['year'], a["month"], a["day"], a["hour"], a["minute"], a["second"])
# 2457358.422222222
# The new signature that accepts a normal date object
# Note that we use keyword "date" argument
jdate2 = jday.JD(date=dt)
# 2457358.422222222
# The new signature that accepts a normal date object
jdate3 = jday2.JD(dt)
# 2457358.422222222
你可以在没有 math.floor()
的情况下重写它:
def jdate(year, month, day, hour, minute, second):
day_fraction = ((second + 60 * minute) + 3600 * hour) / 86400.
return (367 * year - (7 * (year + (month + 9) // 12)) // 4 +
275 * month // 9 + day + (1721013.5 + day_fraction))
你可以简化它;如果你使用 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
def JD(dt):
"""Julian Date: JD(UTC)."""
return (dt - JULIAN_EPOCH + J2000_JD) / DAY
要将 datetime
对象传递给 jdate()
,您可以使用 .timetuple()
方法:
import math
for time_tuple in [(1961, 1, 1), (1968, 2, 1), (1972, 1, 1), (1996, 1, 1)]:
dt = datetime(*time_tuple)
a, b = jdate(*dt.timetuple()[: 6]), JD(dt)
print("{} UTC -> {} JD(UTC)".format(dt, b))
assert math.isclose(a, b), (a, b)
此外,如果需要,您可以使用 dt.year
、dt.month
、dt.day
等属性。
输出
1961-01-01 00:00:00 UTC -> 2437300.5 JD(UTC)
1968-02-01 00:00:00 UTC -> 2439887.5 JD(UTC)
1972-01-01 00:00:00 UTC -> 2441317.5 JD(UTC)
1996-01-01 00:00:00 UTC -> 2450083.5 JD(UTC)
根据 IERS web-site where a recommended "Julian Date" definition is provided,这是正确的。
对于 1900 年 3 月之前和 2100 年 2 月之后的日期,这些公式会产生不同的结果:
import jdcal # pip install jdcal
import astropy.time # pip install astropy
print(" UTC | matlab | datetime | astropy | jdcal")
for year in [1900, 2000, 2100]:
for time_tuple in [(year, 2, 28, 12), (year, 3, 1, 12)]:
dt = datetime(*time_tuple)
matlabJD = jdate(*dt.timetuple()[:6])
datetimeJD = JD(dt)
jdcalJD = sum(jdcal.gcal2jd(*dt.timetuple()[:3])) + .5
astropyJD = astropy.time.Time(dt)
print("{dt} | {matlabJD} | {datetimeJD} | {astropyJD.jd} | {jdcalJD}"
.format(**vars()))
输出
UTC | matlab | datetime | astropy | jdcal
1900-02-28 12:00:00 | 2415078.0 | 2415079.0 | 2415079.0 | 2415079.0
1900-03-01 12:00:00 | 2415080.0 | 2415080.0 | 2415080.0 | 2415080.0
2000-02-28 12:00:00 | 2451603.0 | 2451603.0 | 2451603.0 | 2451603.0
2000-03-01 12:00:00 | 2451605.0 | 2451605.0 | 2451605.0 | 2451605.0
2100-02-28 12:00:00 | 2488128.0 | 2488128.0 | 2488128.0 | 2488128.0
2100-03-01 12:00:00 | 2488130.0 | 2488129.0 | 2488129.0 | 2488129.0
jdate()
你问题中的公式认为 1900
, 2100
是闰年。 datetime
实现、astropy
和 jdcal
库在此处产生相同的结果。
注:朱利安天是一个整数。 JD()
计算 Julian date,其中包括一天的小数部分,请参阅 definitions in the links。
如链接讨论中所述,您应该使用已经制作好的库并在必要时发送补丁,而不是重新发明轮子,以避免由于闰年、浮点问题、错误的时间尺度、细微的差异而导致的简单错误儒略日等术语的定义等
对 python 有点陌生,但试图将其用于卫星轨道分析。我真的没有得到日期时间对象和方法。我希望能够将 datetime 对象传递给一个函数,该函数接受与 datetime 格式基本相同的参数(年、周一、日、小时、分钟、秒)。下面的代码有效,但 has 是更好的方法。请赐教。谢谢!
import jday
import datetime
jdate = jday.JD(2015,12,1,22,8,0) # example
now1 = datetime.datetime.now().strftime("%Y,%m,%d,%H,%M,%S")
now2 = now1.split(",")
now3 = [int(i) for i in now2]
jdatenow = jday.JD(*now3)
print jdatenow
jday 模块是从 David Vallado 的 Astrodynamics 源代码的 Matlab 移植过来的。
import math as m
def JD(yr, mon, day, hr, min, sec):
jd = 367.0 * yr - m.floor(
(7 * (yr + m.floor( (mon + 9) / 12.0) ) ) * 0.25 ) + m.floor(
275 * mon / 9.0 ) + day + 1721013.5 + (
(sec/60.0 + min ) / 60.0 + hr ) / 24.0
return jd
我能想到的最短路径:
now = list(datetime.datetime.now().timetuple())[:-3]
遗憾的是,您不能将日期时间对象直接传递给需要整数的函数。您是否有任何特殊原因无法使用 datetime 提供的字段调用该函数?
now = datetime.now()
jdatenow = jday.JD(now.year, now.month, now.day, now.hour, now.minute, now.second)
或者如果这太麻烦了,把它包起来:
from datetime import datetime
def my_JD(dt):
return jday.JD(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)
jdatenow = my_JD(datetime.now())
这可能比
更容易理解jdatenow = jday.JD(*list(datetime.now().timetuple())[:-3])
鉴于您已经移植了 JD 代码,因此可以将其作为模块 jday 进行控制,也许装饰器就是您想要的正在找。这样做的明显好处是不会破坏函数的原始签名(对于现有的客户端代码),但会根据您的要求增加日期参数的便利性。
还创建了一个 jday2 模块,它与原始 jday 模块相同,但其 JD() 函数改为直接接受日期对象。如果您不需要任何向后兼容性,这是最简单的解决方案。
请参阅下面的工作示例代码:
jday.py
import math as m
import functools
def date_support_wrapper(f):
""" Wraps JD and provides a way to pass a date param
:param f: the original function
:return: the wrapper around the original function
"""
@functools.wraps(f)
def wrap(*args, **kwargs):
if 'date' in kwargs:
d = kwargs['date']
return f(yr=d.year, mon=d.month, day=d.day, hr=d.hour, min=d.minute, sec=d.second)
return f(*args, **kwargs)
return wrap
@date_support_wrapper
def JD(yr, mon, day, hr, min, sec):
jd = 367.0 * yr - m.floor(
(7 * (yr + m.floor((mon + 9) / 12.0))) * 0.25) + m.floor(
275 * mon / 9.0) + day + 1721013.5 + (
(sec / 60.0 + min) / 60.0 + hr) / 24.0
return jd
jday2.py
import math as m
def JD(dt):
""" Same calculation as JD but accepts a date object argument
:param dt: the date object
:return: the JD result
"""
yr, mon, day, hr, min, sec = dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second
jd = 367.0 * yr - m.floor(
(7 * (yr + m.floor((mon + 9) / 12.0))) * 0.25) + m.floor(
275 * mon / 9.0) + day + 1721013.5 + (
(sec / 60.0 + min) / 60.0 + hr) / 24.0
return jd
以及示例客户端代码:
client.py
import datetime
import jday
import jday2
# The date we are interested in
a = dict(year=2015, month=12, day=1, hour=22, minute=8, second=0)
dt = datetime.datetime(**a) # 2015-12-01 22:08:00
# The original signature of the function
jdate1 = jday.JD(a['year'], a["month"], a["day"], a["hour"], a["minute"], a["second"])
# 2457358.422222222
# The new signature that accepts a normal date object
# Note that we use keyword "date" argument
jdate2 = jday.JD(date=dt)
# 2457358.422222222
# The new signature that accepts a normal date object
jdate3 = jday2.JD(dt)
# 2457358.422222222
你可以在没有 math.floor()
的情况下重写它:
def jdate(year, month, day, hour, minute, second):
day_fraction = ((second + 60 * minute) + 3600 * hour) / 86400.
return (367 * year - (7 * (year + (month + 9) // 12)) // 4 +
275 * month // 9 + day + (1721013.5 + day_fraction))
你可以简化它;如果你使用 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
def JD(dt):
"""Julian Date: JD(UTC)."""
return (dt - JULIAN_EPOCH + J2000_JD) / DAY
要将 datetime
对象传递给 jdate()
,您可以使用 .timetuple()
方法:
import math
for time_tuple in [(1961, 1, 1), (1968, 2, 1), (1972, 1, 1), (1996, 1, 1)]:
dt = datetime(*time_tuple)
a, b = jdate(*dt.timetuple()[: 6]), JD(dt)
print("{} UTC -> {} JD(UTC)".format(dt, b))
assert math.isclose(a, b), (a, b)
此外,如果需要,您可以使用 dt.year
、dt.month
、dt.day
等属性。
输出
1961-01-01 00:00:00 UTC -> 2437300.5 JD(UTC)
1968-02-01 00:00:00 UTC -> 2439887.5 JD(UTC)
1972-01-01 00:00:00 UTC -> 2441317.5 JD(UTC)
1996-01-01 00:00:00 UTC -> 2450083.5 JD(UTC)
根据 IERS web-site where a recommended "Julian Date" definition is provided,这是正确的。
对于 1900 年 3 月之前和 2100 年 2 月之后的日期,这些公式会产生不同的结果:
import jdcal # pip install jdcal
import astropy.time # pip install astropy
print(" UTC | matlab | datetime | astropy | jdcal")
for year in [1900, 2000, 2100]:
for time_tuple in [(year, 2, 28, 12), (year, 3, 1, 12)]:
dt = datetime(*time_tuple)
matlabJD = jdate(*dt.timetuple()[:6])
datetimeJD = JD(dt)
jdcalJD = sum(jdcal.gcal2jd(*dt.timetuple()[:3])) + .5
astropyJD = astropy.time.Time(dt)
print("{dt} | {matlabJD} | {datetimeJD} | {astropyJD.jd} | {jdcalJD}"
.format(**vars()))
输出
UTC | matlab | datetime | astropy | jdcal
1900-02-28 12:00:00 | 2415078.0 | 2415079.0 | 2415079.0 | 2415079.0
1900-03-01 12:00:00 | 2415080.0 | 2415080.0 | 2415080.0 | 2415080.0
2000-02-28 12:00:00 | 2451603.0 | 2451603.0 | 2451603.0 | 2451603.0
2000-03-01 12:00:00 | 2451605.0 | 2451605.0 | 2451605.0 | 2451605.0
2100-02-28 12:00:00 | 2488128.0 | 2488128.0 | 2488128.0 | 2488128.0
2100-03-01 12:00:00 | 2488130.0 | 2488129.0 | 2488129.0 | 2488129.0
jdate()
你问题中的公式认为 1900
, 2100
是闰年。 datetime
实现、astropy
和 jdcal
库在此处产生相同的结果。
注:朱利安天是一个整数。 JD()
计算 Julian date,其中包括一天的小数部分,请参阅 definitions in the links。
如链接讨论中所述,您应该使用已经制作好的库并在必要时发送补丁,而不是重新发明轮子,以避免由于闰年、浮点问题、错误的时间尺度、细微的差异而导致的简单错误儒略日等术语的定义等