U su]aB@sdZddlZddlZddlmZddlmZddlm Z ddlm Z dd d d d gZ eGd ddeZ ddZddZddddZd*edddZd+eddd Zd,eddd Zeddd Zdd Zd!d"Zd#d$Zd%d&Zd-edd)d ZdS).zYTime humanizing functions. These are largely borrowed from Django's `contrib.humanize`. N)Enum)total_ordering)gettext)ngettext naturaldelta naturaltime naturalday naturaldate precisedeltac@s4eZdZdZdZdZdZdZdZdZ dZ d d Z d S) UnitrrcCs|j|jkr|j|jkStSN) __class__valueNotImplemented)selfotherr>/opt/alt/python38/lib/python3.8/site-packages/humanize/time.py__lt__#s  z Unit.__lt__N) __name__ __module__ __qualname__ MICROSECONDS MILLISECONDSSECONDSMINUTESHOURSDAYSMONTHSYEARSrrrrrr sr cCs tjSr)dtdatetimenowrrrr_now)sr*cCs |jdkrt}|||S|S)zReturn an "absolute" value for a timedelta, always representing a time distance. Args: delta (datetime.timedelta): Input timedelta. Returns: datetime.timedelta: Absolute timedelta. r)daysr*)deltar)rrr abs_timedelta-s  r-r)c Cs|s t}t|tjr$|}||}n\t|tjr>||}|}nBz t|}tj|d}||}Wn ttfk r~d|fYSX|t|fS)zTurn a value into a date and a timedelta which represents how long ago it was. If that's not possible, return `(None, value)`. )secondsN) r* isinstancer'r( timedeltaint ValueError TypeErrorr-)rr)dater,rrrdate_and_delta<s     r6Tr/)returncCst|}|tjtjtjfkr0td|d|}t||d\}}|dkrP|S|}t|j}t|j } | d} | d} t | d}| s| dkr|dkr|tjkr|j d krt d d |j |j S|tjks|tjkrd |j krd krnn|j d } t d d| | St dS|dkr,t dS|dkrFt dd||Sd|kr^dkrjnnt dSd|krdkrnn|d} t dd| | Sd|krdkrnnt dSd|kr|d} t dd| | Sn| dkrR| dkrt dS|st dd| | S|s.t dd| | S|dkr@t d St d!d"||Sn| dkr|sp| spt d#S|st d$d%| | S|r|dkrt d&St d'd(||Snt d$d%| | Snt d)d*| | SdS)+aReturn a natural representation of a timedelta or number of seconds. This is similar to `naturaltime`, but does not add tense to the result. Args: value (datetime.timedelta): A timedelta or a number of seconds. months (bool): If `True`, then a number of months (based on 30.5 days) will be used for fuzziness between years. minimum_unit (str): The lowest unit that can be used. when (datetime.datetime): Point in time relative to which _value_ is interpreted. Defaults to the current time in the local timezone. Returns: str: A natural representation of the amount of time elapsed. Examples Compare two timestamps in a custom local timezone:: import datetime as dt from dateutil.tz import gettz berlin = gettz("Europe/Berlin") now = dt.datetime.now(tz=berlin) later = now + dt.timedelta(minutes=30) assert naturaldelta(later, when=now) == "30 minutes" zMinimum unit 'z' not supportedr.Nm>@rr%d microsecond%d microsecondsi@B%d millisecond%d millisecondsa momentza second< %d second %d secondsxza minute %d minute %d minutesi zan hour%d hour%d hoursza day%d day%d daysza month%d month %d monthsza yearz1 year, %d dayz1 year, %d daysz1 year, 1 monthz1 year, %d monthz1 year, %d months%d year%d years)r upperr!r rr3r6absr/r+r2 microsecondsr_)rmonths minimum_unitwhenZtmpr5r,Z use_monthsr/r+yearsZ millisecondsminuteshoursrrrrSs!                   Fc Cs|pt}t||d\}}|dkr&|St|tjtjfr@||k}|rLtdntd}t||||d}|tdkrxtdS||S)aReturn a natural representation of a time in a resolution that makes sense. This is more or less compatible with Django's `naturaltime` filter. Args: value (datetime.datetime, int): A `datetime` or a number of seconds. future (bool): Ignored for `datetime`s, where the tense is always figured out based on the current time. For integers, the return value will be past tense by default, unless future is `True`. months (bool): If `True`, then a number of months (based on 30.5 days) will be used for fuzziness between years. minimum_unit (str): The lowest unit that can be used. when (datetime.datetime): Point in time relative to which _value_ is interpreted. Defaults to the current time in the local timezone. Returns: str: A natural representation of the input in a resolution that makes sense. r.Nz %s from nowz%s ago)rUr?r))r*r6r0r'r(r1rRr) rZfuturerSrTrUr)r5r,Zagorrrrs  %b %dc Cszt|j|j|j}Wn2tk r0|YSttfk rJ|YSX|tj}|j dkrlt dS|j dkr~t dS|j dkrt dS| |S)zReturn a natural day. For date values that are tomorrow, today or yesterday compared to present day return representing string. Otherwise, return a string formatted according to `format`. rtodayrZtomorrowZ yesterday) r'r5yearmonthdayAttributeError OverflowErrorr3rZr+rRstrftime)rformatr,rrrr s    c Cszzt|j|j|j}Wn2tk r0|YSttfk rJ|YSXt|tj }|j dkrrt |dSt |S)zKLike `naturalday`, but append a year for dates more than ~five months away.gc@z%b %d %Y) r'r5r\r]r^r_r`r3r-rZr+r )rr,rrrr s   cCs2||kr||dfS||kr$d|fSt||SdS)aDivide `value` by `divisor` returning the quotient and remainder. If `unit` is `minimum_unit`, makes the quotient a float number and the remainder will be zero. The rational is that if `unit` is the unit of the quotient, we cannot represent the remainder because it would require a unit smaller than the `minimum_unit`. >>> from humanize.time import _quotient_and_remainder, Unit >>> _quotient_and_remainder(36, 24, Unit.DAYS, Unit.DAYS, []) (1.5, 0) If unit is in `suppress`, the quotient will be zero and the remainder will be the initial value. The idea is that if we cannot use `unit`, we are forced to use a lower unit so we cannot do the division. >>> _quotient_and_remainder(36, 24, Unit.DAYS, Unit.HOURS, [Unit.DAYS]) (0, 36) In other case return quotient and remainder as `divmod` would do it. >>> _quotient_and_remainder(36, 24, Unit.DAYS, Unit.HOURS, []) (1, 12) rN)divmod)rZdivisorunitrTsuppressrrr_quotient_and_remainders  rfcCs<||kr|||dfS||kr0d|||fS||fSdS)aReturn a tuple with two values. If the unit is in `suppress`, multiply `value1` by `ratio` and add it to `value2` (carry to right). The idea is that if we cannot represent `value1` we need to represent it in a lower unit. >>> from humanize.time import _carry, Unit >>> _carry(2, 6, 24, Unit.DAYS, Unit.SECONDS, [Unit.DAYS]) (0, 54) If the unit is the minimum unit, `value2` is divided by `ratio` and added to `value1` (carry to left). We assume that `value2` has a lower unit so we need to carry it to `value1`. >>> _carry(2, 6, 24, Unit.DAYS, Unit.DAYS, []) (2.25, 0) Otherwise, just return the same input: >>> _carry(2, 6, 24, Unit.DAYS, Unit.SECONDS, []) (2, 6) rNr)Zvalue1Zvalue2Zratiordmin_unitrerrr_carry7s rhcCs6||kr2tD]}||kr ||kr |Sq td|S)aReturn a minimum unit suitable that is not suppressed. If not suppressed, return the same unit: >>> from humanize.time import _suitable_minimum_unit, Unit >>> _suitable_minimum_unit(Unit.HOURS, []).name 'HOURS' But if suppressed, find a unit greather than the original one that is not suppressed: >>> _suitable_minimum_unit(Unit.HOURS, [Unit.HOURS]).name 'DAYS' >>> _suitable_minimum_unit(Unit.HOURS, [Unit.HOURS, Unit.DAYS]).name 'MONTHS' z@Minimum unit is suppressed and no suitable replacement was found)r r3)rgrerdrrr_suitable_minimum_unitVs ricCs,t|}tD]}||krq(||q |S)aExtend suppressed units (if any) with all units lower than the minimum unit. >>> from humanize.time import _suppress_lower_units, Unit >>> [x.name for x in sorted(_suppress_lower_units(Unit.SECONDS, [Unit.DAYS]))] ['MICROSECONDS', 'MILLISECONDS', 'DAYS'] )setr add)rgreurrr_suppress_lower_unitsts  rmr%0.2fc! Cs2t|\}}|dkr|Sdd|D}t|}t||}~t||}|j}|j}|j} tt\} } } } }}}}t |d|||\}}t |d|||\}}t ||d|||\}}t |d|||\}}t |d| ||\}}t || d | ||\}} t | d | ||\}} t | d d | ||\} }d d|fdd|fdd|fdd|fdd|fdd|fdd|fdd| fg}g}t t t|D]\}}|\}}}|d ks|s||krt |||}||krt|d d kr|d|}|||||krnqqnt|d kr|d Sd|dd}|d} td || fS)!a%Return a precise representation of a timedelta. ```pycon >>> import datetime as dt >>> from humanize.time import precisedelta >>> delta = dt.timedelta(seconds=3633, days=2, microseconds=123000) >>> precisedelta(delta) '2 days, 1 hour and 33.12 seconds' ``` A custom `format` can be specified to control how the fractional part is represented: ```pycon >>> precisedelta(delta, format="%0.4f") '2 days, 1 hour and 33.1230 seconds' ``` Instead, the `minimum_unit` can be changed to have a better resolution; the function will still readjust the unit to use the greatest of the units that does not lose precision. For example setting microseconds but still representing the date with milliseconds: ```pycon >>> precisedelta(delta, minimum_unit="microseconds") '2 days, 1 hour, 33 seconds and 123 milliseconds' ``` If desired, some units can be suppressed: you will not see them represented and the time of the other units will be adjusted to keep representing the same timedelta: ```pycon >>> precisedelta(delta, suppress=['days']) '49 hours and 33.12 seconds' ``` Note that microseconds precision is lost if the seconds and all the units below are suppressed: ```pycon >>> delta = dt.timedelta(seconds=90, microseconds=100) >>> precisedelta(delta, suppress=['seconds', 'milliseconds', 'microseconds']) '1.50 minutes' ``` If the delta is too small to be represented with the minimum unit, a value of zero will be returned: ```pycon >>> delta = dt.timedelta(seconds=1) >>> precisedelta(delta, minimum_unit="minutes") '0.02 minutes' >>> delta = dt.timedelta(seconds=0.1) >>> precisedelta(delta, minimum_unit="minutes") '0 minutes' ``` NcSsg|]}t|qSr)r rO).0srrr sz precisedelta..r8r9iQrDr@g.Ar:rrrMrNrKrLrIrJrGrHrErFrArBr=r>r;r<z%dz, r[z %s and %s)r6r rOrirmr+r/rQlistrfrhzipreversedrmathZmodfreplaceappendlenjoinrR)!rrTrerbr5r,rgr+ZsecsZusecsrr r!r"r#r$r%r&rVrSrXrWZmsecsZ_unusedZfmtsZtextsrdZfmtZ singular_txtZ plural_txtZfmt_txtheadtailrrrr shC          )Tr/N)FTr/N)rY)r/rrn)__doc__r(r'ruenumr functoolsrZi18nrrRr__all__r r*r-r6strrrr r rfrhrirmr rrrrsJ      q *!