Source code for celme.dates

import datetime
import math
import doctest
import typing 
from .durations import Duration

# ========================================================
# ========================================================
# === DATE
# ========================================================
# ========================================================

[docs]class Date: """ Class to convert dates for astronomy *Date formats are:* | now = Now. e.g. "now" | jd = Julian day. e.g. 24504527.45678 | iso = ISO 8601. e.g. 2018-02-28T12:34:55.23 | sql = ISO 8601. e.g. 2018-02-28 12:34:55.23 | ymdhms = Calendar. e.g. 2018 2 28 12 34 55.23 | equinox = Equinox. e.g. J2000,0 | digits = Pure digits e.g. 20180228123455.23 *Usage:* First, instanciate an object from the class: :: date = Date() Second, assign a date in any date format: :: date.date("2018-02-28T12:34:55") Third, get the converted date: :: jd = date.jd() date = date.date() iso = date.iso() ymdhms = date.ymdhms() equinox = date.equinox() *Informations:* All dates are in UTC. Some other useful methods: :: help(Date) Date().infos("doctest") Date().infos("doc_methods") """ # ======================================================== # === attributs # ======================================================== _B1850 = 2396758.203 _B1900 = 2415020.3135 _B1950 = 2433282.4235 _B1975 = 2442413.478 _B2000 = 2451544.533 _B2025 = 2460675.588 _B2050 = 2469806.643 _B2100 = 2488068.753 _J1900 = 2415020.0000 _J1950 = 2433282.5000 _J2000 = 2451545.0000 _J2050 = 2469807.5000 _J2100 = 2488070.0000 # ======================================================== # === internal methods # ======================================================== def _init(self,date="") -> None: """ Initialize internal attributes. :param date: date is a date in any supported format (cf. help(Date)) :type date: any :returns: None :rtype: None :Example: >>> objdate = Date() >>> objdate._init() """ self._init_date = date self._init_dateformat = 0 self._computed_jd = 0 self._computed_iso = 0 self._computed_iso_nb_subdigit = 3 self._computed_iso_letter = 'T' self._computed_ymdhms = 0 self._computed_digits = 0 self._computed_digits_nb_subdigit = 3 self._computed_equinox = 0 self._computed_equinox_year_type = "J" self._computed_equinox_nb_subdigit = 1 self._jd = 0 self._iso = 0 self._ymdhms = 0 self._equinox = 0 def _is_number(self,s) -> bool: """ Return True if the string is a number else return False. :param s: A string to test :type s: string :returns: True is the string can be concerted into a float :rtype: bool :Example: >>> objdate = Date() >>> objdate._is_number("3e5") True >>> objdate._is_number("3a5") False """ try: float(s) return True except ValueError: pass try: import unicodedata unicodedata.numeric(s) return True except (TypeError, ValueError): pass return False def _duration2day(self, duration) -> float: """ Return a duration in day unit from a duration in dhms format. :param duration: A string formated as "2d7h23m12.5s" :type duration: string :returns: duration expressed in day and fraction of day :rtype: float :Example: >>> objdate = Date() >>> objdate._duration2day("2d7h23m12.5s") 2.3077835648148146 """ duration = str(duration) duration = duration.upper() cars = "+-.E0123456789" units = "DHMS" dur = 0 k1 = -1 k2 = -1 k = 0 div = 0 for car in duration: if car in cars: if k1 == -1: k1 = k k2 = k elif car in units: if (k1>=0 and k2>=0): div = 0 if car=='D': div = 1. elif car=='H': div = 24. elif car=='M': div = 1440. elif car=='S': div = 86400. if div>0: n = float(duration[k1:k2+1]) dur += n/div k1 = -1 k2 = -1 k += 1 if (div==0 and dur==0 and k1>=0 and k2>=k1): n = float(duration[k1:k2+1]) dur += n return dur def _date_compare(self, date, operator): """ Comparaison of dates for various operators. :param date: A date in any supported format (cf. help(Date)) :type date: Date() :param operator : Operator such as == != > >= < <= :type operator : string :returns: The logic result of the comparison. :rtype: bool :Example: >>> objdate1 = Date() >>> objdate2 = Date() >>> objdate1.date("2018 02 28"); objdate2.date("2018 02 27"); objdate1._date_compare(objdate2,">") '2018 02 28' '2018 02 27' True .. note:: Does not account for the modulo. """ if self._computed_jd == 0: self.jd() if date._computed_jd == 0: date.jd() res = False if (self._computed_jd == 1) and (date._computed_jd == 1): toeval = str(self._jd)+" "+operator+" "+str(date._jd) res = eval(toeval) return res # ======================================================== # === date methods # ========================================================
[docs] def date_date2jd(self,date) -> typing.Tuple[int, float]: """ Compute a julian day from any date format :param date: A string formated as "2d7h23m12.5s" :type date: string :returns: A tuple of init_dateformat, julian day. init_dateformat: The identified format of the input: * 0 = Error, format not known * 1 = Now * 2 = Equinox * 3 = Sql * 4 = Calendar * 5 = ISO 8601 * 6 = Julian day * 7 = Modified Julian day * 8 = Digits :rtype: tuple(int, float) :Example: >>> objdate = Date() >>> objdate.date_date2jd("2018-02-28T12:34:55.234") (5, 2458178.0242503937) .. note:: Prefer using objdate.date() followed by objdate.jd(). """ # --- First we do not process if date is ever a Date object if (isinstance(date, Date)): return date # --- Decode the date jd = 0 init_dateformat = 0 str_date = str(date).upper() str_split = str_date.split(" ") str_nsplit = len(str_split) if str_date == "NOW": # style NOW utc_datetime = datetime.datetime.utcnow() day = utc_datetime.day + ((((utc_datetime.microsecond*1e-6) + utc_datetime.second)/60. + utc_datetime.minute)/60. + utc_datetime.hour)/24. error, jd = self.date_ymd2jd(utc_datetime.year, utc_datetime.month, day) init_dateformat = 1 elif (str_date[0] is "B") or (str_date[0] is "J"): # style J2000,0 error, jd = self.date_equinox2jd(str_date) init_dateformat = 2 elif (str_nsplit is 2): # style SQL 2018-01-02 23:02:45.456 iso_date = str_split[0] + "T" + str_split[1] error, jd = self.date_iso2jd(iso_date) init_dateformat = 3 elif (str_nsplit is 3): # style calenday 2018 01 02.4567 str_split = [ float(x) for x in str_split] error, jd = self.date_ymd2jd(str_split[0],str_split[1],str_split[2]) init_dateformat = 4 elif (str_nsplit is 4): # style calenday 2018 01 02 05.324 str_split = [ float(x) for x in str_split] error, jd = self.date_ymdhms2jd(str_split[0],str_split[1],str_split[2],str_split[3]) init_dateformat = 4 elif (str_nsplit is 5): # style calenday 2018 01 02 05 12.1809 str_split = [ float(x) for x in str_split] error, jd = self.date_ymdhms2jd(str_split[0],str_split[1],str_split[2],str_split[3],str_split[4]) init_dateformat = 4 elif (str_nsplit is 6): # style calenday 2018 01 02 05 12 56.789 str_split = [ float(x) for x in str_split] error, jd = self.date_ymdhms2jd(str_split[0],str_split[1],str_split[2],str_split[3],str_split[4],str_split[5]) init_dateformat = 4 elif (str_nsplit is 1) and (str_date.find("T") > 6): # style ISO 2018-01-02T23:02:45.456 error, jd = self.date_iso2jd(str_date) init_dateformat = 5 elif (self._is_number(str_date) is True): # style is julian day or MJD # MJD = JD - 2400000.5 (SAO in 1957) # digits as 20180316 jd = float(str_date) init_dateformat = 6 if (math.log10(jd) > 7.2): # --- digits error, jd = self.date_digits2jd(str_date) init_dateformat = 8 elif (math.log10(jd) < 5): # --- MJD jd += 2400000.5 init_dateformat = 7 return init_dateformat, jd
[docs] def date_iso2jd(self,string) -> tuple: """ Compute a julian day from a ISO8601 date :param string: A string formated in ISO 8601 :type string: string :returns: A tuple of error, julian day. error = 0 means no error :rtype: tuple(int, float) :Example: >>> objdate = Date() >>> objdate.date_iso2jd("2018-02-28T12:34:55.234") (0, 2458178.0242503937) First integer is an error code. 0 = no problem. .. note:: Prefer using objdate.date() followed by objdate.jd(). """ error = 0 k1 = string.find("-",1) k2 = string.find("-",k1+1) kt = string.find("T",k2+1) if (kt==-1): kt = string.find("T",k2+1) k3 = string.find(":",kt+1) k4 = string.find(":",k3+1) d=1 hh=0 mm=0 ss=0.0 if (k2 > -1): y = int(string[0:k1]) m = int(string[k1+1:k2]) if (kt == -1): d = float(string[k2+1:]) else: d = int(string[k2+1:kt]) if (k3 > -1): hh = int(string[kt+1:k3]) d += hh/24. if (k4 == -1): mm = float(string[k3+1:]) d += mm/1440. else: mm = int(string[k3+1:k4]) d += mm/1440. ss = float(string[k4+1:]) d += ss/86400. error, jd = self.date_ymd2jd(y,m,d) else: # pb format error = 1 return error, jd
[docs] def date_jd2iso(self, jd, nb_subdigit=3, letter='T') -> tuple: """ Compute a ISO8601 date from a julian day :param jd: A julian day :type jd: float :param nb_subdigit: The number of digits returned after the seconds. :type nb_subdigit: int :param letter: The letter to separe date end time. If letter is "" then the output format sticks all digits without any characters :-T. So the format is no longer ISO but useful for a pure digit code. :type letter: int :returns: A tuple of error, string of a date formatted into ISO8601. error = 0 means no error. :rtype: tuple(int, float) :Example: >>> objdate = Date() >>> objdate.date_jd2iso(2458178.0242503937) (0, '2018-02-28T12:34:55.234') .. note:: Prefer using objdate.date() followed by objdate.iso() """ error, y, m, d, hh, mm, ss = self.date_jd2ymdhms(jd) nb_prefixdigit = nb_subdigit+3 if (nb_subdigit < 0): nb_subdigit = 0 if (nb_subdigit == 0): nb_prefixdigit -= 1 if (letter==''): fstring = "{:04d}{:02d}{:02d}{}{:02d}{:02d}{:0"+str(nb_prefixdigit)+"."+str(nb_subdigit)+"f}" else: fstring = "{:04d}-{:02d}-{:02d}{}{:02d}:{:02d}:{:0"+str(nb_prefixdigit)+"."+str(nb_subdigit)+"f}" res = fstring.format(y, m, d, letter, hh, mm, ss) return error, res
[docs] def date_equinox2jd(self,string): """ Compute a julian day from a equinoxal date :param string: date string is a string in Equinox format (cf. help(Date)) :type string: string :returns: A tuple of error, julian day. error = 0 means no error :rtype: tuple(int, float) :Example: >>> objdate = Date() >>> objdate.date_equinox2jd("J2025,0") (0, 2460676.25) .. note:: Prefer using objdate.date() followed by objdate.jd() """ error = 0 t = string[0] s = string[1:].replace(',','.') a = float(s) jd = 0 if t is "J": if (a == 1900): jd = self._J1900 elif (a == 1950): jd = self._J1950 elif (a == 2000): jd = self._J2000 elif (a == 2050): jd = self._J2050 elif (a == 2100): jd = self._J2100 else: jd = 2451545.0+(a-2000.0)*365.25; elif t is "B": if (a == 1850): jd = self._B1850 elif (a == 1900): jd = self._B1900 elif (a == 1950): jd = self._B1950 elif (a == 1975): jd = self._B1975 elif (a == 2000): jd = self._B2000 elif (a == 2025): jd = self._B2025 elif (a == 2050): jd = self._B2050 elif (a == 2100): jd = self._B2100 else: error = 2 return error,jd
[docs] def date_digits2jd(self,string): """ Compute a julian day from a date with only digits :param string: A string formated in digits :type string: string :returns: A tuple of error, julian day. error = 0 means no error :rtype: tuple(int, float) :Example: >>> objdate = Date() >>> objdate.date_iso2jd("2018-02-28T12:34:55.234") (0, 2458178.0242503937) First integer is an error code. 0 = no problem. .. note:: Prefer using objdate.date() followed by objdate.digits(). """ error = 0 k1 = string.find("-",1) k2 = string.find("-",k1+1) kt = string.find("T",k2+1) if (kt==-1): kt = string.find("T",k2+1) k3 = string.find(":",kt+1) k4 = string.find(":",k3+1) d=1 hh=0 mm=0 ss=0.0 if (k2 > -1): y = int(string[0:k1]) m = int(string[k1+1:k2]) if (kt == -1): d = float(string[k2+1:]) else: d = int(string[k2+1:kt]) if (k3 > -1): hh = int(string[kt+1:k3]) d += hh/24. if (k4 == -1): mm = float(string[k3+1:]) d += mm/1440. else: mm = int(string[k3+1:k4]) d += mm/1440. ss = float(string[k4+1:]) d += ss/86400. error, jd = self.date_ymd2jd(y,m,d) else: # pb format error = 1 return error, jd
[docs] def date_jd2digits(self, jd, nb_subdigit=3): """ Compute a date only with digits from a julian day :param jd: A julian day :type jd: float :param nb_subdigit: The number of digits returned after the seconds. :type nb_subdigit: int :returns: A tuple of error, string of a date formatted into ISO8601. error = 0 means no error. :rtype: tuple(int, float) :Example: >>> objdate = Date() >>> objdate.date_jd2iso(2458178.0242503937) (0, '2018-02-28T12:34:55.234') .. note:: Prefer using objdate.date() followed by objdate.digits() """ return self.date_jd2iso(jd,nb_subdigit,"")
[docs] def date_jd2equinox(self,jd,year_type="",nb_subdigit=1): """ Compute an equinoxal date from a julian day :param jd: A julian day :type jd: float :param year_type: "B" (Bessel) or "J" (Julian) or "" for automatic choice :type year_type: string :param nb_subdigit: The number of digits returned after the year. :type nb_subdigit: int :returns: A tuple of error, string of a date formatted into ISO8601. error = 0 means no error. :rtype: tuple(int, float) :Example: >>> objdate = Date() >>> objdate.date_jd2equinox(2458178.0242503937) (0, 'J2018.2') .. note:: Prefer using objdate.date() followed by objdate.equinox() """ error = 0 eps=1e-3 if (year_type==""): year_type="J" if ((math.fabs(jd-2415020.3135)<eps) or (math.fabs(jd-2433282.4235)<eps)): year_type="B" if (year_type=="J"): # julian a=(jd-2451545.0)/365.25+2000.0 chaine0="J" if (year_type=="B"): # besselian a = 1900.0 + (jd - 2415020.31352) / 365.242198781 chaine0 = "B" if (nb_subdigit>0): fstring = "{:."+str(nb_subdigit)+"f}" equinox = chaine0 + fstring.format(a) else: equinox = chaine0 + "{:.0f}".format(a) return error, equinox
[docs] def date_ymdhms2jd(self, y:int, m:int, d:int, hh:int=0, mm:int=0, ss:float=0) -> tuple: """ Compute a julian day from a calendar date :param y: Year :type y: int :param m: Month :type m: int :param d: Day :type d: int :param hh: Hour :type hh: int :param mm: Minutes :type mm: int :param ss: Seconds :type ss: float :returns: A tuple of error, float corresponding to the julian day. error = 0 means no error. :rtype: tuple(int, float) :Example: >>> objdate = Date() >>> objdate.date_ymdhms2jd(2017,3,12,0,23,12.34) (0, 2457824.516115046) First integer is an error code. 0 = no problem. :Related topics: Prefer using objdate.date() followed by objdate.jd() """ d += ( hh + ( mm + ss/60.) /60.) /24.; error, jd = self.date_ymd2jd(y, m, d) return error, jd
[docs] def date_ymd2jd(self,year, month, day): """ Compute a julian day from a calendar date :param year: Year :type year: int :param month: Month :type month: int :param day: Day and fraction of the day :type day: float :Example: >>> objdate = Date() >>> objdate.date_ymd2jd(2017,3,12.64232) (0, 2457825.14232) First integer is an error code. 0 = no problem. :Related topics: Prefer using objdate.date() followed by objdate.jd() """ error = 0 a=year; m=month; j=day; if m <= 2: a=a-1 m=m+12 aa=math.floor(a/100) bb=2-aa+math.floor(aa/4) jd=math.floor(365.25*(a+4716))+math.floor(30.6001*(m+1))+bb-1524.5 jd=jd+j; if (jd<2299160.5) : jd=math.floor(365.25*(a+4716))+math.floor(30.6001*(m+1))-1524.5; jd=jd+j return error,jd
[docs] def date_jd2ymd(self,jd): """ Compute a calendar date from a julian day :param jd: Julian day :type jd: float :Example: >>> objdate = Date() >>> objdate.date_jd2ymd(2457825.14232) (0, 2017, 3, 12.64232000010088) First integer is an error code. 0 = no problem. Following items are: * year = year * month = month * day = day and fraction of day :Related topics: Prefer using objdate.date() followed by objdate.ymdhms() """ error=0; jd+=.5 z=math.floor(jd) f=jd-z if (z<2299161.): a=z else: alpha=math.floor((z-1867216.25)/36524.25) a=z+1+alpha-math.floor(alpha/4) b=a+1524 c=math.floor(((b-122.1)/365.25)) d=math.floor(365.25*c) e=math.floor((b-d)/30.6001) d=b-d-math.floor(30.6001*e)+f if e<14: m = (int)(e-1) else: m = (int)(e-13) if m>2: y = (int)(c-4716) else: y = (int)(c-4715) return error, y, m, d
[docs] def date_jd2ymdhms(self,jd): """ Compute a calendar date from a julian day :param jd: Julian day :type jd: float :Example: >>> objdate = Date() >>> objdate.date_jd2ymdhms(2457824.516115046) (0, 2017, 3, 12, 0, 23, 12.339983582496643) First integer is an error code. 0 = no problem. Following items are: * y = year * m = month * d = day * hh = hour * mm = minutes * ss = seconds :Related topics: Prefer using objdate.date() followed by objdate.ymdhms() """ error, y, m, day = self.date_jd2ymd(jd) d = int(math.floor(day)) hh = 0 mm = 0 ss = 0 if (error==0): r = (day-d)*24 hh = int(math.floor(r)) r = (r-hh)*60 mm = int(math.floor(r)) ss = (r-mm)*60 return error, y, m, d, hh, mm, ss
# ======================================================== # === get/set methods # ========================================================
[docs] def date(self, date=""): """ Set the input date in any format :param date: date is a date in any supported format (cf. help(Date)) :type date: any :returns: The input date. :rtype: string :Example: >>> objdate = Date() >>> objdate.date("2018-02-28T12:34:55.234") '2018-02-28T12:34:55.234' .. note:: After using objdate.date() get conversions with methods as objdate.jd() or objdate.iso(). """ if date != "": if isinstance(date, str) == True: dt = date.upper() else: dt = "" if (date != self._init_date) or (dt == "NOW"): self._init(date) return self._init_date
[docs] def jd(self): """ Get the date in julian day format :returns: The julian day. :rtype: float :Example: >>> objdate = Date() >>> objdate.date("2018-02-28T12:34:55.234") '2018-02-28T12:34:55.234' >>> objdate.jd() 2458178.0242503937 .. note:: Before use objdate.date() to set the input date. """ if (self._computed_jd == 0): init_dateformat, jd = self.date_date2jd(self._init_date) if (init_dateformat > 0): self._init_dateformat = init_dateformat self._computed_jd = 1 self._jd = jd return self._jd return -1 return self._jd
[docs] def iso(self, nb_subdigit=3,letter='T'): """ Get the date in ISO 8601 format :param nb_subdigit: The number of digits returned after the seconds. :type nb_subdigit: int :param letter: The letter to separe date end time. If letter is "" then the output format sticks all digits without any characters :-T. So the format is no longer ISO but useful for a pure digit code. :type letter: int :Example: >>> objdate = Date() >>> objdate.date("2018-02-28T12:34:55.234") '2018-02-28T12:34:55.234' >>> objdate.iso(2) '2018-02-28T12:34:55.23' :Related topics: Before use objdate.date() to set the input date. """ if (self._computed_iso == 0) or (self._computed_iso_nb_subdigit != nb_subdigit) or (self._computed_iso_letter != letter): if (self._computed_jd == 0): self.jd() if (self._init_dateformat > 0): error, iso = self.date_jd2iso(self._jd, nb_subdigit, letter) if error==0: self._computed_iso = 1 self._iso = iso self._computed_iso_nb_subdigit = nb_subdigit self._computed_iso_letter = letter return self._iso return -1 return self._iso
[docs] def ymdhms(self): """ Get the date in ymdhms format :Example: >>> objdate = Date() >>> objdate.date("2018-02-28T12:34:55.234") '2018-02-28T12:34:55.234' >>> objdate.ymdhms() [2018, 2, 28, 12, 34, 55.23401856422424] :Related topics: Before use objdate.date() to set the input date. """ if (self._computed_ymdhms == 0): if (self._computed_jd == 0): self.jd() if (self._init_dateformat > 0): error, *ymdhms = self.date_jd2ymdhms(self._jd) if error==0: self._computed_ymdhms = 1 self._ymdhms = ymdhms return self._ymdhms return -1 return self._ymdhms
[docs] def digits(self, nb_subdigit=3): """ Get the date in digits format :param nb_subdigit: The number of digits returned after the seconds. :type nb_subdigit: int :Example: >>> objdate = Date() >>> objdate.date("2018-02-28T12:34:55.234") '2018-02-28T12:34:55.234' >>> objdate.iso(2) '2018-02-28T12:34:55.23' :Related topics: Before use objdate.date() to set the input date. """ if (self._computed_digits == 0) or (self._computed_digits_nb_subdigit != nb_subdigit): if (self._computed_jd == 0): self.jd() if (self._init_dateformat > 0): error, digits = self.date_jd2digits(self._jd, nb_subdigit) if error==0: self._computed_digits = 1 self._digits = digits self._computed_digits_nb_subdigit = nb_subdigit return self._digits return -1 return self._digits
[docs] def equinox(self, year_type="J", nb_subdigit=1): """ Get the date in equinox format :param year_type: "B" (Bessel) or "J" (Julian) or "" for automatic choice :type year_type: string :param nb_subdigit: The number of digits returned after the year. :type nb_subdigit: int :Example: >>> objdate = Date() >>> objdate.date("2018-02-28T12:34:55.234") '2018-02-28T12:34:55.234' >>> objdate.equinox() 'J2018.2' :Related topics: Before use objdate.date() to set the input date. """ if (self._computed_equinox == 0) or (self._computed_equinox_year_type != year_type) or (self._computed_equinox_nb_subdigit != nb_subdigit): if (self._computed_jd == 0): self.jd() if (self._init_dateformat > 0): error, equinox = self.date_jd2equinox(self._jd,year_type,nb_subdigit) if error==0: self._computed_equinox = 1 self._equinox = equinox self._computed_equinox_year_type = year_type self._computed_equinox_nb_subdigit = nb_subdigit return self._equinox return -1 return self._equinox
# ======================================================== # === debug methods # ========================================================
[docs] def infos(self, action): """ To get informations about this class :param action: A command to run a debug action (see examples). :type action: string :Example: :: Date().infos("doctest") Date().infos("doc_methods") Date().infos("internal_attributes") Date().infos("public_methods") """ if (action == "doc_methods"): publics = [x for x in dir(self) if x[0]!="_"] for public in publics: varname = "{}".format(public) if (callable(getattr(self,varname))==True): print("\n{:=^40}".format(" method "+varname+" ")) t = "Date()."+varname+".__doc__" tt =eval(t) print(tt) if (action == "doctest"): if __name__ == "__main__": print("\n{:~^40}".format("doctest")) #doctest.testmod(verbose=True, extraglobs={'objdate': Date()}) doctest.testmod(verbose=True) if (action == "internal_attributes"): internals = [x for x in dir(self) if x[0]=="_" and x[1]!="_"] for internal in internals: varname = "{}".format(internal) #if (hasattr(self,varname)==True): if (callable(getattr(self,varname))==False): print(varname + "=" + str(getattr(self,varname))) if (action == "public_methods"): publics = [x for x in dir(self) if x[0]!="_"] for public in publics: varname = "{}".format(public) if (callable(getattr(self,varname))==True): print(varname)
# ======================================================== # === special methods # ======================================================== def __init__(self, date=""): """ Object initialization where date is the input in any format :param date: A input date in any format. :type date: string date is a date in any supported format (cf. help(Date)) """ self._init(date)
[docs] def __add__(self, duration): """ Add a duration to a date :param duration: Duration in dhms format (e.g 3d20h5m3s). :type duration: string :Example: >>> objdate = Date() >>> objdate.date("2018-02-28T12:34:55.234") ; date = objdate + "12m45s" ; date.iso() '2018-02-28T12:34:55.234' '2018-02-28T12:47:40.234' """ if self._computed_jd == 0: self.jd() if self._computed_jd == 1: jd = self._jd else: return Date() duration = Duration(duration) day = duration.day() jd += day return Date(jd)
[docs] def __radd__(self, duration): """ Right addition a duration to a date """ return self + duration
[docs] def __iadd__(self, duration): """ Add a duration to a date """ return self + duration
[docs] def __sub__(self, object_or_duration): """ Subtract a duration to a date (returns an object date) or Compute the duration between two date objects. :param object_or_duration: Duration in dhms format (e.g 3d20h5m3s) :type object_or_duration: Date object :Example: >>> objdate = Date() >>> objdate.date("2018-02-28T12:34:55.234") ; date = objdate - "12m45s" ; date.iso() '2018-02-28T12:34:55.234' '2018-02-28T12:22:10.234' >>> objdate.date("2018-02-28T12:34:55.234") ; objdate2 = Date("2018-02-25T12:34:55.234") ; days = objdate - objdate2 ; print(days) '2018-02-28T12:34:55.234' 3.0 """ res = 0 if self._computed_jd == 0: self.jd() if isinstance(object_or_duration, Date) == True: date = object_or_duration if date._computed_jd == 0: date.jd() if (self._computed_jd == 1) and (date._computed_jd == 1): res = self._jd - date._jd else: duration = object_or_duration if self._computed_jd == 1: jd = self._jd else: return Date() duration = Duration(duration) day = duration.day() jd -= day return Date(jd) return res
[docs] def __rsub__(self, date): """ Right subtraction only for a date to another date """ if isinstance(date, Date) == True: return self - date else: return date
[docs] def __isub__(self, duration): """ Subtract a duration to a date :param duration: Duration in dhms format (e.g 3d20h5m3s) :type duration: str :Example: >>> objdate = Date() >>> objdate.date("2018-02-28T12:34:55.234") ; objdate -= "12m45s" ; objdate.iso() '2018-02-28T12:34:55.234' '2018-02-28T12:22:10.234' """ return self - duration
[docs] def __eq__(self, date): """ Comparaison of dates. Return True if dates are defined and equals. :param date: An object instancied on Date :type date: Date :Example: >>> objdate = Date() >>> objdate.date("2018 02 28"); objdate2 = Date("2018 02 28"); objdate == objdate2 '2018 02 28' True """ return self._date_compare( date, "==")
[docs] def __ne__(self, date): """ Comparaison of dates. Return True if dates are defined and not equals. :param date: An object instancied on Date :type date: Date :Example: >>> objdate = Date() >>> objdate.date("2018 02 28"); objdate2 = Date("2018 02 28"); objdate != objdate2 '2018 02 28' False """ return self._date_compare( date, "!=")
[docs] def __gt__(self, date): """ Comparaison of dates: date1 > date 2. Return True if dates are defined and date1 > date 2. :param date: An object instancied on Date :type date: Date :Example: >>> objdate = Date() >>> objdate.date("2018 02 28"); objdate2 = Date("2018 02 27"); objdate > objdate2 '2018 02 28' True """ return self._date_compare( date, ">")
[docs] def __ge__(self, date): """ Comparaison of dates: date1 >= date 2. Return True if dates are defined and date1 >= date 2. :param date: An object instancied on Date :type date: Date :Example: >>> objdate = Date() >>> objdate.date("2018 02 28"); objdate2 = Date("2018 02 27"); objdate >= objdate2 '2018 02 28' True """ return self._date_compare( date, ">=")
[docs] def __lt__(self, date): """ Comparaison of dates: date1 < date 2. Return True if dates are defined and date1 < date 2. :param date: An object instancied on Date :type date: Date :Example: >>> objdate = Date() >>> objdate.date("2018 02 26"); objdate2 = Date("2018 02 27"); objdate < objdate2 '2018 02 26' True """ return self._date_compare( date, "<")
[docs] def __le__(self, date): """ Comparaison of dates: date1 <= date 2. Return True if dates are defined and date1 <= date 2. :param date: An object instancied on Date :type date: Date :Example: >>> objdate = Date() >>> objdate.date("2018 02 26"); objdate2 = Date("2018 02 27"); objdate <= objdate2 '2018 02 26' True """ return self._date_compare( date, "<=")
# ======================================================== # ======================================================== # ========================================================