Search code examples
pythondatetimesatellitejulian-date

Formatting python datetime object as argument


Somewhat new to python but trying to use it for satellite orbit analysis. I'm really not getting the datetime object and methods. I want to be able to pass a datetime object to a function that accepts arguments in essentially the same format that datetime does (year, mon, day, hour, min, sec). The code below works but there has to be a better way. Please enlighten me. Thanks!

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 module is ported over from Matlab of David Vallado's Astrodynamics source code.

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

Solution

  • Given you have ported over the JD code, and therefore have control over it as module jday, perhaps a decorator is what you are looking for. This has the obvious benefit of not breaking the original signature of the function (for existing client code), but adds the convenience of a date param as you requested.

    Have also created a jday2 module which is the same as the original jday module but whose JD() function instead accepts a date object directly. This is the simplest solution if you don't need any backwards compatibility.

    Please see working example code below:

    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
    

    And example client code:

    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