Ris*_*ran 33 python formatting datetime
我对python很新.我有两个日期时间对象.我需要计算它们之间的时间值,然后以特定格式显示输出.
Alpha_TimeObj = datetime.datetime(int(AlphaTime.strftime('%Y')), int(AlphaTime.strftime('%m')), int(AlphaTime.strftime('%d')), int(AlphaTime.strftime('%H')), int(AlphaTime.strftime('%M')), int(AlphaTime.strftime('%S')))
Beta_TimeObj = datetime.datetime(int(BetaTime.strftime('%Y')), int(BetaTime.strftime('%m')), int(BetaTime.strftime('%d')), int(BetaTime.strftime('%H')), int(BetaTime.strftime('%M')), int(BetaTime.strftime('%S')))
Turnaround_TimeObj = Beta_TimeObj - Alpha_TimeObj
Run Code Online (Sandbox Code Playgroud)
此Turnaround_TimeObj时间增量的一个示例是"2天,22:13:45".我想格式化输出,但我无法这样做.
print Turnaround_TimeObj.strftime('%H hrs %M mins %S secs')
Run Code Online (Sandbox Code Playgroud)
不起作用.
我知道这样做的一种方法是将其转换为秒,然后进行divmodding以获得所需的格式.如;
totalSeconds = Turnaround_TimeObj.seconds
hours, remainder = divmod(totalSeconds, 3600)
minutes, seconds = divmod(remainder, 60)
print '%s:%s:%s' % (hours, minutes, seconds)
Run Code Online (Sandbox Code Playgroud)
但我想知道我是否可以使用像strftime这样的日期时间函数在一行中完成它.
编辑:实际上转换为秒也不起作用.如果我将时间增量"1天,3:42:54"转换为秒使用
totalSeconds = Turnaround_TimeObj.seconds
Run Code Online (Sandbox Code Playgroud)
totalSeconds值显示为13374而不是99774. ie.它忽略了"日"的价值.
Sha*_*hin 52
但我想知道我是否可以使用像strftime这样的日期时间函数在一行中完成它.
据我所知,没有内置的方法可以strftime做到这一点.如果你经常这样做,你可以创建自己的功能,例如
def strfdelta(tdelta, fmt):
d = {"days": tdelta.days}
d["hours"], rem = divmod(tdelta.seconds, 3600)
d["minutes"], d["seconds"] = divmod(rem, 60)
return fmt.format(**d)
Run Code Online (Sandbox Code Playgroud)
用法:
>>> print strfdelta(delta_obj, "{days} days {hours}:{minutes}:{seconds}")
1 days 20:18:12
>>> print strfdelta(delta_obj, "{hours} hours and {minutes} to go")
20 hours and 18 to go
Run Code Online (Sandbox Code Playgroud)
如果你想使用更接近timedelta我们可以使用的字符串格式的字符串格式strftime.
from string import Template
class DeltaTemplate(Template):
delimiter = "%"
def strfdelta(tdelta, fmt):
d = {"D": tdelta.days}
d["H"], rem = divmod(tdelta.seconds, 3600)
d["M"], d["S"] = divmod(rem, 60)
t = DeltaTemplate(fmt)
return t.substitute(**d)
Run Code Online (Sandbox Code Playgroud)
用法:
>>> print strfdelta(delta_obj, "%D days %H:%M:%S")
1 days 20:18:12
>>> print strfdelta(delta_obj, "%H hours and %M to go")
20 hours and 18 to go
Run Code Online (Sandbox Code Playgroud)
totalSeconds值显示为13374而不是99774. ie.它忽略了"日"的价值.
请注意,在上面的示例中,您可以使用string.Template获取"day"值.
或者,从Python 2.7开始,timedelta有一个total_seconds()方法,它返回持续时间中包含的总秒数.
unu*_*tbu 16
在Python2.7或更高版本中,您可以使用total_seconds方法:
import datetime as dt
turnaround = dt.timedelta(days = 1, hours = 3, minutes = 42, seconds = 54)
total_seconds = int(turnaround.total_seconds())
hours, remainder = divmod(total_seconds,60*60)
minutes, seconds = divmod(remainder,60)
print('{} hrs {} mins {} secs'.format(hours,minutes,seconds))
Run Code Online (Sandbox Code Playgroud)
产量
27 hrs 42 mins 54 secs
Run Code Online (Sandbox Code Playgroud)
在Python2.6或更早版本中,您可以total_seconds自己计算:
total_seconds = turnaround.seconds + turnaround.days*24*60*60
Run Code Online (Sandbox Code Playgroud)
(对于更通用的公式,包括微秒,请参阅上面的链接).
mpo*_*ett 14
Shawn Chin的答案很好,但是它的一个问题是,如果你跳过你的格式中的特定元素(如他的第二个例子中只有几小时和几分钟......不是几天或几秒)那么那个时间会从你的结果中消失.您可以修改它以修复该问题,并通过仅处理实际出现在格式字符串中的关键字来获得更准确的结果.
class DeltaTemplate(Template):
delimiter = '%'
def strfdelta(tdelta, fmt):
d = {}
l = {'D': 86400, 'H': 3600, 'M': 60, 'S': 1}
rem = int(tdelta.total_seconds())
for k in ( 'D', 'H', 'M', 'S' ):
if "%{}".format(k) in fmt:
d[k], rem = divmod(rem, l[k])
t = DeltaTemplate(fmt)
return t.substitute(**d)
Run Code Online (Sandbox Code Playgroud)
用法:
>>> print strfdelta(delta_obj, "%D days %H:%M:%S")
1 days 20:18:12
>>> print strfdelta(delta_obj, "%H hours and %M to go")
44 hours and 18 to go
Run Code Online (Sandbox Code Playgroud)
虽然这对于格式化是不灵活的,因为你不能应用任何转换字符串并结束这样丑陋的事情:
>>> delta_obj = timedelta(minutes=5, seconds=2)
>>> print strfdelta(delta_obj, "%H:%M:%S")
0:5:2
Run Code Online (Sandbox Code Playgroud)
但是,您可以采用相同的方法并将其应用于string.Formatter而不是string.Template并获得更好的效果.
from string import Formatter
def strfdelta(tdelta, fmt):
f = Formatter()
d = {}
l = {'D': 86400, 'H': 3600, 'M': 60, 'S': 1}
k = map( lambda x: x[1], list(f.parse(fmt)))
rem = int(tdelta.total_seconds())
for i in ('D', 'H', 'M', 'S'):
if i in k and i in l.keys():
d[i], rem = divmod(rem, l[i])
return f.format(fmt, **d)
Run Code Online (Sandbox Code Playgroud)
用法:
>>> delta_obj = timedelta(days=1, hours=20, minutes=18, seconds=12)
>>> print strfdelta(delta_obj, "{D} days {H}:{M}:{S}")
1 days 20:18:12
>>> print strfdelta(delta_obj, "{H} hours and {M} to go")
44 hours and 18 to go
>>> delta_obj = timedelta(minutes=5, seconds=2)
>>> print strfdelta(delta_obj, "{H:02}h{M:02}m{S:02}s")
00h05m02s
>>> print strfdelta(delta_obj, "{H:02}:{M:02}:{S:02}")
00:05:02
Run Code Online (Sandbox Code Playgroud)
gum*_*ion 14
Shawn Chin的回答略有变化- 也解决了mpouncett引发的后续问题 - 用前导零填充小时,分钟和秒来确保所有3个元素都使用2个位置(更符合strftime中这些字段的规范)):
from string import Template
class DeltaTemplate(Template):
delimiter = "%"
def strfdelta(tdelta, fmt):
d = {"D": tdelta.days}
hours, rem = divmod(tdelta.seconds, 3600)
minutes, seconds = divmod(rem, 60)
d["H"] = '{:02d}'.format(hours)
d["M"] = '{:02d}'.format(minutes)
d["S"] = '{:02d}'.format(seconds)
t = DeltaTemplate(fmt)
return t.substitute(**d)
Run Code Online (Sandbox Code Playgroud)
以下是对某些示例值的测试:
from datetime import timedelta
for seconds in [0, 1, 59, 60, 61, 3599, 3600, 3601]:
print strfdelta(timedelta(0, seconds), '%H:%M:%S')
Run Code Online (Sandbox Code Playgroud)
这是输出:
00:00:00
00:00:01
00:00:59
00:01:00
00:01:01
00:59:59
01:00:00
01:00:01
Run Code Online (Sandbox Code Playgroud)
您可以使用具有更友好的relativedelta对象的dateutil模块.
import dateutil
import datetime
alpha = datetime.datetime(2012, 1, 16, 6, 0)
beta = datetime.datetime(2012, 1, 18, 10, 42, 57, 230301)
delta = dateutil.relativedelta(beta, alpha)
Run Code Online (Sandbox Code Playgroud)
这会给你一个看起来像的对象增量
>>> delta
relativedelta(days=+2, hours=+4, minutes=+42, seconds=+57, microseconds=+230301)
Run Code Online (Sandbox Code Playgroud)
然后你可以做
print('turnaround %i hrs %i mins %i secs' % (delta.days * 24 + delta.hours, delta.minutes, delta.seconds))
Run Code Online (Sandbox Code Playgroud)
)
def to_time(seconds):
delta = datetime.timedelta(seconds=seconds)
return str(delta.days) + 'd ' + (datetime.datetime.utcfromtimestamp(0) + delta).strftime('%H:%M')
Run Code Online (Sandbox Code Playgroud)
先前的答案似乎没有处理UTC“左”时区的负时间增量值(例如由pytz产生)。如每文档,timedelta对象被归一化,和负timedelta由负表示day实例属性。从文档:
请注意,负值的归一化起初可能会令人惊讶。
然后
timedelta 对象的字符串表示形式与其内部表示形式类似。这导致负时间增量的一些不寻常的结果。
例如:
>>> td = timedelta(seconds=-30)
>>> str(td)
'-1 day, 23:59:30'
>>> repr(td)
'datetime.timedelta(-1, 86370)'
Run Code Online (Sandbox Code Playgroud)
鉴于此示例 timedelta,Shawn Chin 的接受答案和gumption 的答案return'23:59:30'以及mpounsett 的 answer '-1:59:30'。
我认为为了以更易读的方式打印负和正时间增量,我们需要明确处理时区对象的符号和绝对值:
def strfdelta(td, fmt):
# Get the timedelta’s sign and absolute number of seconds.
sign = "-" if td.days < 0 else "+"
secs = abs(td).total_seconds()
# Break the seconds into more readable quantities.
days, rem = divmod(secs, 86400) # Seconds per day: 24 * 60 * 60
hours, rem = divmod(rem, 3600) # Seconds per hour: 60 * 60
mins, secs = divmod(rem, 60)
# Format (as per above answers) and return the result string.
t = DeltaTemplate(fmt)
return t.substitute(
s=sign,
D="{:d}".format(int(days)),
H="{:02d}".format(int(hours)),
M="{:02d}".format(int(mins)),
S="{:02d}".format(int(secs)),
)
Run Code Online (Sandbox Code Playgroud)
这个函数返回一个更易读的字符串表示:
>>> strfdelta(td, "%s%H:%M:%S") # Note that %s refers to the timedelta’s sign.
'-00:00:30'
>>> strfdelta(timedelta(days=-1), "%s%D %H:%M:%S")
'-1 00:00:00'
>>> strfdelta(timedelta(days=-1, minutes=5), "%s%D %H:%M:%S")
'-0 23:55:00'
>>> strfdelta(timedelta(days=-1, minutes=-5), "%s%D %H:%M:%S")
'-1 00:05:00'
Run Code Online (Sandbox Code Playgroud)
……或者在更实际的时区上下文中:
>>> import pytz
>>> import datetime
>>> td = pytz.timezone("Canada/Newfoundland").utcoffset(datetime.datetime.now())
>>> td
datetime.timedelta(-1, 77400)
>>> strfdelta(td, fmt="%s%H:%M")
'-02:30'
>>> td = pytz.timezone("Australia/Eucla").utcoffset(datetime.datetime.now())
>>> td
datetime.timedelta(0, 31500)
>>> strfdelta(td, fmt="%s%H:%M")
'+08:45'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
55853 次 |
| 最近记录: |