将python datetime对象格式化为参数

将python datetime对象格式化为参数,python,datetime,satellite,julian-date,Python,Datetime,Satellite,Julian Date,python有点新,但尝试将其用于卫星轨道分析。我真的没有得到datetime对象和方法。我希望能够将datetime对象传递给一个函数,该函数接受与datetime格式(年、月、日、小时、分钟、秒)基本相同的参数。下面的代码可以工作,但有一种更好的方法。请开导我。谢谢 import jday import datetime jdate = jday.JD(2015,12,1,22,8,0) # example now1 = datetime.datetime.now().strftime(

python有点新,但尝试将其用于卫星轨道分析。我真的没有得到datetime对象和方法。我希望能够将datetime对象传递给一个函数,该函数接受与datetime格式(年、月、日、小时、分钟、秒)基本相同的参数。下面的代码可以工作,但有一种更好的方法。请开导我。谢谢

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模块是从davidvallado的天体动力学源代码的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()。是否有任何特殊原因使您无法使用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
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
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
jday2.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
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
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
和示例客户端代码:

client.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
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
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()
即可重写它:

你可以简化它;如果使用
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
等属性

输出 这是正确的根据


对于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()))
输出
jdate()
你问题中的公式认为
1900
2100
是闰年。
datetime
实现、
astropy
jdcal
库在这里产生相同的结果

注意:Julian day是一个整数
JD()
计算一个包含一天小数的儒略日期,请参阅


正如链接讨论中提到的,您应该使用已经制作好的库,并在必要时发送补丁,而不是重新设计轮子,以避免由于闰年、浮点问题、错误的时间尺度、术语朱利安日定义的细微差异等而导致的简单错误。

好主意,显然,我对python或datetime了解不够,无法以这种方式使用这些字段。谢谢。我还得多读一些关于装潢概念的书,但我想这正是我希望做的。更改jday函数以接受日期对象。谢谢。@JesseReich-请您将此标记为公认的答案:)修饰符是使用“面向方面编程”(AOP)添加/修改给定函数的现有行为而不实际更改该函数本身的一种好方法。这取决于您需要什么-如果您没有理由支持这两种函数参数类型,那么只需修改现有JD签名以接受日期对象,然后从该日期对象解析出您想要的参数。@JesseReich-刚刚更新了答案(最终..)包括一个单独的JayDay2.Py模块,如果你认为装饰者对你的需求太多,这可能是你所需要的。内联版本对你来说更好吗?类似于
now=[int(i)for i in datetime.datetime.now().strftime(“%Y、%m、%d、%H、%m、%S”)。split(“,”)
nonrelated:该公式在1900年和2100年一整天都是错误的,在卫星轨道分析中,分秒可能是重要的,根据计算的细节可以选择几个时间尺度。最终选择的任何解决方案的输出都应正确标记时间刻度。一个简单的“UTC”标签会引起接收输出的人的怀疑,因为各种试图支持Julian日期的软件库以不同的方式处理闰秒。@GerardAshton:UTC在我的回答中是UTC的意思。单击答案中带有IER的链接。AJ.F。塞巴斯蒂安:[一个IAU来源]指出UTC是在1960年启动的,因此将日期/时间标记为1900年是可疑的。@GerardAshton:1900的目的是比较不同的实现:差异是一整天,比时间尺度(如UT1、TAI)之间的任何差异都大得多@GerardAshton:如果你需要亚秒级的精度,那么你可能应该使用IERS链接中推荐的统一时间刻度(如GPS)。UTC是非统一的(由于闰秒)。