timedelta를 문자열로 형식화
저는 Python 초보자 (2 주)이며 datetime.timedelta
개체의 서식을 지정하는 데 문제가 있습니다.
여기에 내가하려는 일이 있습니다. 객체 목록이 있고 객체 클래스의 멤버 중 하나가 이벤트 기간을 나타내는 timedelta 객체입니다. 해당 지속 시간을시 : 분 형식으로 표시하고 싶습니다.
나는 이것을하기 위해 다양한 방법을 시도했지만 어려움을 겪고있다. 현재 접근 방식은 시간과 분을 반환하는 객체의 클래스에 메소드를 추가하는 것입니다. timedelta.seconds를 3600으로 나누고 반올림하여 시간을 얻을 수 있습니다. 나머지 초를 가져 와서 몇 분으로 변환하는 데 문제가 있습니다.
그건 그렇고, 나는 프레젠테이션 Google AppEngine
을 Django Templates
위해 함께 사용 하고 있습니다.
시간 델타를 str ()을 사용하여 문자열로 변환 할 수 있습니다. 예를 들면 다음과 같습니다.
import datetime
start = datetime.datetime(2009,2,10,14,00)
end = datetime.datetime(2009,2,10,16,00)
delta = end-start
print(str(delta))
# prints 2:00:00
아시다시피, .seconds
속성 에 액세스하여 timedelta 객체에서 total_seconds를 가져올 수 있습니다 .
파이썬은 내장 함수 divmod()
를 제공합니다 .
s = 13420
hours, remainder = divmod(s, 3600)
minutes, seconds = divmod(remainder, 60)
print '{:02}:{:02}:{:02}'.format(int(hours), int(minutes), int(seconds))
# result: 03:43:40
또는 모듈로와 빼기를 조합하여 시간과 나머지로 변환 할 수 있습니다.
# arbitrary number of seconds
s = 13420
# hours
hours = s // 3600
# remaining seconds
s = s - (hours * 3600)
# minutes
minutes = s // 60
# remaining seconds
seconds = s - (minutes * 60)
# total time
print '{:02}:{:02}:{:02}'.format(int(hours), int(minutes), int(seconds))
# result: 03:43:40
>>> str(datetime.timedelta(hours=10.56))
10:33:36
>>> td = datetime.timedelta(hours=10.505) # any timedelta object
>>> ':'.join(str(td).split(':')[:2])
10:30
timedelta
객체를 str()
함수에 전달하면 단순히 입력하면 사용되는 것과 동일한 서식 코드가 호출됩니다 print td
. 초를 원하지 않기 때문에 문자열을 콜론 (3 부분)으로 나누고 처음 2 부분 만 다시 묶을 수 있습니다.
def td_format(td_object):
seconds = int(td_object.total_seconds())
periods = [
('year', 60*60*24*365),
('month', 60*60*24*30),
('day', 60*60*24),
('hour', 60*60),
('minute', 60),
('second', 1)
]
strings=[]
for period_name, period_seconds in periods:
if seconds > period_seconds:
period_value , seconds = divmod(seconds, period_seconds)
has_s = 's' if period_value > 1 else ''
strings.append("%s %s%s" % (period_value, period_name, has_s))
return ", ".join(strings)
그는 이미 타임 델타 객체를 가지고 있으므로 내장 메소드 total_seconds ()를 사용하여 초로 변환 한 다음 divmod ()를 사용하여 시간과 분을 얻으십시오.
hours, remainder = divmod(myTimeDelta.total_seconds(), 3600)
minutes, seconds = divmod(remainder, 60)
# Formatted only for hours and minutes as requested
print '%s:%s' % (hours, minutes)
이것은 시간 델타가 며칠 또는 몇 년인지에 관계없이 작동합니다.
개인적으로 humanize
라이브러리를 사용합니다 .
>>> import datetime
>>> humanize.naturalday(datetime.datetime.now())
'today'
>>> humanize.naturalday(datetime.datetime.now() - datetime.timedelta(days=1))
'yesterday'
>>> humanize.naturalday(datetime.date(2007, 6, 5))
'Jun 05'
>>> humanize.naturaldate(datetime.date(2007, 6, 5))
'Jun 05 2007'
>>> humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=1))
'a second ago'
>>> humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=3600))
'an hour ago'
물론, 그것은 당신이 찾고있는 정확한 대답을 제공하지는 않습니다 (실제로 str(timeA - timeB)
몇 시간이 지나면 디스플레이를 빠르게 읽을 수 없음 humanize
을 알았습니다 . 사람이 읽을 수 있으며 현지화가 잘되어 있습니다.
장고의 contrib.humanize
모듈 에서 영감을 얻은 것 같습니다. 장고를 사용하고 있기 때문에 아마도 그것을 사용해야합니다.
나는 이것이 오래된 대답이라는 것을 알고 있지만 이것을 위해 사용 datetime.utcfromtimestamp()
합니다. 초가 걸리고 datetime
다른 형식과 같이 형식화 할 수있는를 반환합니다 datetime
.
duration = datetime.utcfromtimestamp(end - begin)
print duration.strftime('%H:%M')
시간 부분의 법적 범위를 유지하는 한 작동해야합니다. 즉 시간이 <= 23이므로 1234 : 35가 반환되지 않습니다.
질문자는 일반적인 것보다 더 좋은 형식을 원합니다.
>>> import datetime
>>> datetime.timedelta(seconds=41000)
datetime.timedelta(0, 41000)
>>> str(datetime.timedelta(seconds=41000))
'11:23:20'
>>> str(datetime.timedelta(seconds=4102.33))
'1:08:22.330000'
>>> str(datetime.timedelta(seconds=413302.33))
'4 days, 18:48:22.330000'
따라서 실제로는 일이 0이고 생략 된 텍스트와 "n 일, h : m : s"라는 텍스트가있는 두 가지 형식이 있습니다. 그러나 초에는 분수가있을 수 있으며 인쇄물에 선행 0이 없으므로 열이 지저분합니다.
당신이 그것을 좋아한다면 여기 내 루틴이 있습니다 :
def printNiceTimeDelta(stime, etime):
delay = datetime.timedelta(seconds=(etime - stime))
if (delay.days > 0):
out = str(delay).replace(" days, ", ":")
else:
out = "0:" + str(delay)
outAr = out.split(':')
outAr = ["%02d" % (int(float(x))) for x in outAr]
out = ":".join(outAr)
return out
출력을 dd : hh : mm : ss 형식으로 반환합니다.
00:00:00:15
00:00:00:19
02:01:31:40
02:01:32:22
나는 이것에 몇 년을 더하는 것에 대해 생각했지만 출력은 1 년 이상 안전하기 때문에 독자에게는 연습으로 남아 있습니다.
>>> str(datetime.timedelta(seconds=99999999))
'1157 days, 9:46:39'
다음은 timedelta
객체 또는 일반 숫자 (초 또는 분 등의 형식)를 형식이 지정된 문자열 로 변환하는 범용 함수입니다 . 나는 중복 질문에 대한 mpounsett의 환상적인 대답 을 취하여 조금 더 유연하고 가독성을 높이고 문서를 추가했습니다.
다음과 같이 할 수 있기 때문에 지금까지 가장 유연한 답변이라는 것을 알게 될 것입니다.
- 하드 코딩되는 대신 즉시 문자열 형식을 사용자 정의하십시오.
- 문제없이 일정한 시간 간격을 두십시오 (아래 예 참조).
함수:
from string import Formatter
from datetime import timedelta
def strfdelta(tdelta, fmt='{D:02}d {H:02}h {M:02}m {S:02}s', inputtype='timedelta'):
"""Convert a datetime.timedelta object or a regular number to a custom-
formatted string, just like the stftime() method does for datetime.datetime
objects.
The fmt argument allows custom formatting to be specified. Fields can
include seconds, minutes, hours, days, and weeks. Each field is optional.
Some examples:
'{D:02}d {H:02}h {M:02}m {S:02}s' --> '05d 08h 04m 02s' (default)
'{W}w {D}d {H}:{M:02}:{S:02}' --> '4w 5d 8:04:02'
'{D:2}d {H:2}:{M:02}:{S:02}' --> ' 5d 8:04:02'
'{H}h {S}s' --> '72h 800s'
The inputtype argument allows tdelta to be a regular number instead of the
default, which is a datetime.timedelta object. Valid inputtype strings:
's', 'seconds',
'm', 'minutes',
'h', 'hours',
'd', 'days',
'w', 'weeks'
"""
# Convert tdelta to integer seconds.
if inputtype == 'timedelta':
remainder = int(tdelta.total_seconds())
elif inputtype in ['s', 'seconds']:
remainder = int(tdelta)
elif inputtype in ['m', 'minutes']:
remainder = int(tdelta)*60
elif inputtype in ['h', 'hours']:
remainder = int(tdelta)*3600
elif inputtype in ['d', 'days']:
remainder = int(tdelta)*86400
elif inputtype in ['w', 'weeks']:
remainder = int(tdelta)*604800
f = Formatter()
desired_fields = [field_tuple[1] for field_tuple in f.parse(fmt)]
possible_fields = ('W', 'D', 'H', 'M', 'S')
constants = {'W': 604800, 'D': 86400, 'H': 3600, 'M': 60, 'S': 1}
values = {}
for field in possible_fields:
if field in desired_fields and field in constants:
values[field], remainder = divmod(remainder, constants[field])
return f.format(fmt, **values)
데모:
>>> td = timedelta(days=2, hours=3, minutes=5, seconds=8, microseconds=340)
>>> print strfdelta(td)
02d 03h 05m 08s
>>> print strfdelta(td, '{D}d {H}:{M:02}:{S:02}')
2d 3:05:08
>>> print strfdelta(td, '{D:2}d {H:2}:{M:02}:{S:02}')
2d 3:05:08
>>> print strfdelta(td, '{H}h {S}s')
51h 308s
>>> print strfdelta(12304, inputtype='s')
00d 03h 25m 04s
>>> print strfdelta(620, '{H}:{M:02}', 'm')
10:20
>>> print strfdelta(49, '{D}d {H}h', 'h')
2d 1h
내 datetime.timedelta
물건은 하루 이상 갔다. 여기 또 다른 문제가 있습니다. 위의 모든 토론은 하루 미만을 가정합니다. A timedelta
는 실제로 일, 초 및 마이크로 초의 튜플입니다. 위의 논의는 td.seconds
joe와 마찬가지로 사용해야 하지만 일이 있으면 초 값에 포함되지 않습니다.
2 개의 datetimes와 인쇄 일과 시간 사이에 시간이 걸리고 있습니다.
span = currentdt - previousdt
print '%d,%d\n' % (span.days,span.seconds/3600)
나는 Occam의 Razor 접근법을 진지하게 고려할 것입니다.
td = str(timedelta).split('.')[0]
마이크로 초가없는 문자열을 반환합니다.
datetime.timedelta 객체를 재생성하려면 다음을 수행하십시오.
h,m,s = re.split(':', td)
new_delta = datetime.timedelta(hours=int(h),minutes=int(m),seconds=int(s))
2 년 후, 나는이 언어를 좋아한다!
위의 Joe의 예제 값에 따라 모듈러스 산술 연산자를 사용합니다.
td = datetime.timedelta(hours=10.56)
td_str = "%d:%d" % (td.seconds/3600, td.seconds%3600/60)
파이썬에서 정수 나누기는 기본적으로 반올림됩니다. 보다 명확하게하려면 math.floor () 또는 math.ceil ()을 적절하게 사용하십시오.
나는 이것을 위해 humanfriendly
파이썬 라이브러리를 사용했다 . 매우 잘 작동한다.
import humanfriendly
from datetime import timedelta
delta = timedelta(seconds = 321)
humanfriendly.format_timespan(delta)
'5 minutes and 21 seconds'
https://pypi.org/project/humanfriendly/ 에서 이용 가능
def seconds_to_time_left_string(total_seconds):
s = int(total_seconds)
years = s // 31104000
if years > 1:
return '%d years' % years
s = s - (years * 31104000)
months = s // 2592000
if years == 1:
r = 'one year'
if months > 0:
r += ' and %d months' % months
return r
if months > 1:
return '%d months' % months
s = s - (months * 2592000)
days = s // 86400
if months == 1:
r = 'one month'
if days > 0:
r += ' and %d days' % days
return r
if days > 1:
return '%d days' % days
s = s - (days * 86400)
hours = s // 3600
if days == 1:
r = 'one day'
if hours > 0:
r += ' and %d hours' % hours
return r
s = s - (hours * 3600)
minutes = s // 60
seconds = s - (minutes * 60)
if hours >= 6:
return '%d hours' % hours
if hours >= 1:
r = '%d hours' % hours
if hours == 1:
r = 'one hour'
if minutes > 0:
r += ' and %d minutes' % minutes
return r
if minutes == 1:
r = 'one minute'
if seconds > 0:
r += ' and %d seconds' % seconds
return r
if minutes == 0:
return '%d seconds' % seconds
if seconds == 0:
return '%d minutes' % minutes
return '%d minutes and %d seconds' % (minutes, seconds)
for i in range(10):
print pow(8, i), seconds_to_time_left_string(pow(8, i))
Output:
1 1 seconds
8 8 seconds
64 one minute and 4 seconds
512 8 minutes and 32 seconds
4096 one hour and 8 minutes
32768 9 hours
262144 3 days
2097152 24 days
16777216 6 months
134217728 4 years
직장에서의 초과 근무 계산 결과와 비슷한 문제가있었습니다. 값이 하루보다 길고 값이 음수 인 경우에도 항상 HH : MM에 값이 표시되어야합니다. 표시된 솔루션 중 일부를 결합하여 다른 사람 이이 솔루션을 유용하게 사용할 수 있습니다. timedelta 값이 음수이면 divmod 방법으로 표시된 대부분의 솔루션이 즉시 작동하지 않는다는 것을 깨달았습니다.
def td2HHMMstr(td):
'''Convert timedelta objects to a HH:MM string with (+/-) sign'''
if td < datetime.timedelta(seconds=0):
sign='-'
td = -td
else:
sign = ''
tdhours, rem = divmod(td.total_seconds(), 3600)
tdminutes, rem = divmod(rem, 60)
tdstr = '{}{:}:{:02d}'.format(sign, int(tdhours), int(tdminutes))
return tdstr
HH : MM 문자열에 대한 타임 델타 :
td2HHMMstr(datetime.timedelta(hours=1, minutes=45))
'1:54'
td2HHMMstr(datetime.timedelta(days=2, hours=3, minutes=2))
'51:02'
td2HHMMstr(datetime.timedelta(hours=-3, minutes=-2))
'-3:02'
td2HHMMstr(datetime.timedelta(days=-35, hours=-3, minutes=-2))
'-843:02'
import datetime
hours = datetime.timedelta(hours=16, minutes=30)
print((datetime.datetime(1,1,1) + hours).strftime('%H:%M'))
from django.utils.translation import ngettext
def localize_timedelta(delta):
ret = []
num_years = int(delta.days / 365)
if num_years > 0:
delta -= timedelta(days=num_years * 365)
ret.append(ngettext('%d year', '%d years', num_years) % num_years)
if delta.days > 0:
ret.append(ngettext('%d day', '%d days', delta.days) % delta.days)
num_hours = int(delta.seconds / 3600)
if num_hours > 0:
delta -= timedelta(hours=num_hours)
ret.append(ngettext('%d hour', '%d hours', num_hours) % num_hours)
num_minutes = int(delta.seconds / 60)
if num_minutes > 0:
ret.append(ngettext('%d minute', '%d minutes', num_minutes) % num_minutes)
return ' '.join(ret)
이것은 다음을 생성합니다 :
>>> from datetime import timedelta
>>> localize_timedelta(timedelta(days=3660, minutes=500))
'10 years 10 days 8 hours 20 minutes'
이 기능을 확인하십시오-timedelta 객체를 문자열 'HH : MM : SS'로 변환합니다
def format_timedelta(td):
hours, remainder = divmod(td.total_seconds(), 3600)
minutes, seconds = divmod(remainder, 60)
hours, minutes, seconds = int(hours), int(minutes), int(seconds)
if hours < 10:
hours = '0%s' % int(hours)
if minutes < 10:
minutes = '0%s' % minutes
if seconds < 10:
seconds = '0%s' % seconds
return '%s:%s:%s' % (hours, minutes, seconds)
timedelta obj가 이미 있다면 해당 obj를 문자열로 변환하십시오. 문자열의 마지막 3자를 제거하고 인쇄하십시오. 그러면 초 부분이 잘리고 나머지 부분은시 : 분 형식으로 인쇄됩니다.
t = str(timedeltaobj)
print t[:-3]
t1 = datetime.datetime.strptime(StartTime, "%H:%M:%S %d-%m-%y")
t2 = datetime.datetime.strptime(EndTime, "%H:%M:%S %d-%m-%y")
return str(t2-t1)
그래서 :
StartTime = '15:28:53 21-07-13'
EndTime = '15:32:40 21-07-13'
보고:
'0:03:47'
도와 주셔서 감사합니다. 나는 당신의 많은 아이디어를 가지고 그것을 함께 모아서 당신의 생각을 알려주세요.
클래스에 다음과 같이 두 가지 방법을 추가했습니다.
def hours(self):
retval = ""
if self.totalTime:
hoursfloat = self.totalTime.seconds / 3600
retval = round(hoursfloat)
return retval
def minutes(self):
retval = ""
if self.totalTime:
minutesfloat = self.totalTime.seconds / 60
hoursAsMinutes = self.hours() * 60
retval = round(minutesfloat - hoursAsMinutes)
return retval
내 장고에서는 이것을 사용했습니다 (sum은 객체이며 사전에 있습니다).
<td>{{ sum.0 }}</td>
<td>{{ sum.1.hours|stringformat:"d" }}:{{ sum.1.minutes|stringformat:"#02.0d" }}</td>
참고 URL : https://stackoverflow.com/questions/538666/format-timedelta-to-string
'Programing' 카테고리의 다른 글
django order_by 쿼리 세트, 오름차순 및 내림차순 (0) | 2020.04.10 |
---|---|
jQuery .load 응답이 캐시되지 않도록 중지 (0) | 2020.04.10 |
누가 1 = 1을 사용하고 왜 (0) | 2020.04.10 |
일반 목록 / 열거 가능을 DataTable로 변환 하시겠습니까? (0) | 2020.04.10 |
텍스트 상자에 Enter 키를 누르는 사용자를위한 JQuery 이벤트? (0) | 2020.04.10 |