Python中几个日期相关的使用

960 阅读4分钟

本文主要总结几个Python中日期相关的使用。主要使用的是 datetime 模块,datetime模块中的date类包含年月日、time类包含时分秒以及微秒和时区,datetime类是日期和时间的组合包含年月日和时分秒以及微秒和时区。

字符串 ⇋ 日期

日期转字符串使用strftime,字符串转日期使用strptime。两者的区别如下:

strftimestrptime
使用根据给定的格式将对象转换为一个字符串根据给定的相应格式将一个字符串转换为一个 datetime对象
方法的类型实例方法类方法
谁的方法date; datetime; time 实例datetime
使用示意strftime(format)strptime(date_string, format)

日期转字符串

使用strftime(format),要注意这是实例的方法。

1.date类实例转化为字符串:

from datetime import date

today = date.today()
today_str = today.strftime('%Y-%m-%d')
print(today_str) # 2021-06-14

用到的代表年月日等的%Y等符号的含义,查看:格式代码

2.datetime类实例转化为字符串:

from datetime import datetime

dt = datetime(2021, 6, 14, 15, 2, 3)
dt_str = dt.strftime('%Y/%m/%d %H:%M:%S')
print(dt_str) # 2021/06/14 15:02:03

构造器datetime.datatime,创建一个datetime实例。用法:

datetime.datetime(year, month, day, hour=0,minute=0,second=0, microsecond=0,tzinfo=None, *, fold=0)

3.time类实例转化为字符串

from datetime import time

t = time(15, 3, 0)
t_str = t.strftime('%H:%M:%S')
print(t_str) # 15:03:00

字符串转日期

使用strptime(date_string, format),要注意这是类的方法。

from datetime import datetime

dt = datetime.strptime('2021/06/14 15:05:06', '%Y/%m/%d %H:%M:%S')
print(dt, type(dt)) # 2021-06-14 15:05:06 <class 'datetime.datetime'>

时间间隔计算

使用dateutil包能非常方便地进行日期相关的处理,当然也可以使用python自带的模块实现。

根据时间间隔得到日期时间

得到距离当前时间n秒/分钟/小时/天/周/月/年的开始时间。

方法一:使用Python自带的模块

主要datetime模块的timedelta方法。timedelta代表的是一个时间间隔,是两个日期或者时间的差。用法:

datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)

实现代码:

import calendar
from datetime import datetime, timedelta

def get_start_time(time_number, time_unit):
    '''
    得到距离当前时间time_number秒/分钟/小时/天/周/月/年的时间
    '''
    if type(time_number) != int or type(time_unit) != str:
        raise Exception('传入的time_number需为整数类型,time_unit需为字符串类型')
    now = datetime.now()
    unit_list = ['seconds', 'minutes', 'hours', 'days', 'weeks']
    delta_params = None
    if time_unit in unit_list:
        delta_params = {
            time_unit: time_number
        }
        delta = timedelta(**delta_params)
        start_time = now - delta
        return start_time
    if time_unit == 'months':
        now_year = now.year
        now_month = now.month
        now_day = now.day
        start_year = now_year
        start_month = now_month - time_number
        start_day = now_day
        # 前time_number个月跨年了,比如当前是2021年3月,要取5月前的日期,那就是2020年10月
        if start_month <= 0:
            months_interval = abs(start_month)
            years_interval = months_interval // 12
            start_year = now_year - years_interval - 1
            start_month = 12 - months_interval % 12

        weekday, month_days = calendar.monthrange(year=start_year, month=start_month)
        # 前time_number个月没有当前日期,比如今天是3月31号,2月只有28号,那么取2月最后的一天28号
        if now_day > month_days:
            start_day = month_days
        start_time = now.replace(year=start_year, month=start_month, day=start_day)
        return start_time
    
    if time_unit == 'years':
        now_year = now.year
        now_month = now.month
        now_day = now.day
        start_year = now_year - time_number
        start_day = now_day
        weekday, month_days = calendar.monthrange(year=start_year, month=now_month)
        # 前time_number年对应的月没有当前日期,比如今天是2月29号,前1年的2月只有2月28号,那么取28号
        if now_day > month_days:
            start_day = month_days
        start_time = now.replace(year=start_year, month=now_month, day=start_day)
        return start_time

# 测试
x = get_start_time(1, 'years')
print(x)

1.因为timedelta方法只支持到周,所以关于月和年的计算需要自行处理,需要考虑跨年和日期的特殊情况。

2.date类实例和datetime类实例都有replace方法,它们的用法分别如下:

(1)返回一个date实例:

date.replace(year=self.year, month=self.month, day=self.day)

比如将今天的年份换成2020年,可以使用:

from datetime import date

today = date.today()
n = today.replace(year=2020)
print(n) # 2020-06-14

(2)返回一个datetime实例:

datetime.replace(year=self.year, month=self.month, day=self.day, hour=self.hour, minute=self.minute, second=self.second, microsecond=self.microsecond, tzinfo=self.tzinfo, *, fold=0)

比如将今天的月份换成5月份,可以使用:

from datetime import datetime

now = datetime.now()
m = now.replace(month=5)
print(m) # 2021-05-14 16:27:44.384520

3.calendar模块的calendar.monthrange(year, month)方法返回指定年月的第一天的工作日和该月的总天数。

方法二:使用dateutil

安装:pip install python-dateutil

使用relativedelta方法,用法:

relativedelta.relativedelta(years, months, weeks, days, hours, minutes, seconds, microseconds)

实现代码:

from dateutil.relativedelta import relativedelta

def get_start_time_v1(time_number, time_unit):
    unit_list = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds']
    if type(time_number) != int:
        raise Exception('传入的time_number类型需为整数')
    if time_unit not in unit_list:
        raise Exception('传入的单位time_unit不正确')
    now = datetime.now()
    delta_params = {
        time_unit: -time_number
    }
    start_time = now + relativedelta(**delta_params)
    return start_time

# 测试
y = get_start_time_v1(1, 'years')
print(y)

得到2个月前的时间间隔,使用:

relativedelta.relativedelta(months=-2)

得到2个月零2天的时间间隔,使用:

relativedelta.relativedelta(months=-2, days=-2)

根据日期时间得到时间间隔

计算两个时间之间的秒数。

def get_time_interval(start_time, end_time):
    start_time = datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S')
    end_time = datetime.strptime(end_time, '%Y-%m-%d %H:%M:%S')
    if type(start_time) != datetime or type(end_time) != datetime:
        raise Exception('传入的参数格式不正确')
    if end_time < start_time:
        raise Exception('结束时间小于开始时间')
    interval = end_time - start_time
    return interval.seconds

# 测试
z = get_time_interval('2021-06-14 14:55:00', '2021-06-14 14:55:02')
print(z) # 2 秒

timedelta实例的属性:

属性
days-999999999 至 999999999 ,含999999999
seconds0 至 86399,包含86399
microseconds0 至 999999,包含999999

如果不是计算两个时间的秒数,想要计算两个日期之间的年的差异或者月的差异,使用relativedelta方法比较方便:

def get_time_interval_v1(start_time, end_time):
    start_time = datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S')
    end_time = datetime.strptime(end_time, '%Y-%m-%d %H:%M:%S')
    if type(start_time) != datetime or type(end_time) != datetime:
        raise Exception('传入的参数格式不正确')
    if end_time < start_time:
        raise Exception('结束时间小于开始时间')
    interval = relativedelta(end_time, start_time)
    return interval.years * 12 + interval.months
    
o = get_time_interval_v1('2021-06-14 14:55:00', '2022-07-14 14:55:02')
print(o) # 13 月

获取时间戳

>>> from datetime import datetime
>>> now = datetime.now()
>>> timestamp = datetime.timestamp(now)
>>> timestamp
1654677564.575214
>>> int(timestamp)
1654677564