脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|shell|

服务器之家 - 脚本之家 - Python - 封装 Python 时间处理库创建自己的TimeUtil类示例

封装 Python 时间处理库创建自己的TimeUtil类示例

2023-05-02 12:58忆想不到的晖 Python

这篇文章主要为大家介绍了封装 Python 时间处理库创建自己的TimeUtil类示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪

简介

在日常的Python开发中,处理时间和日期的需求是非常常见的。尽管Python内置了 datetime 和 time 模块,但在某些情况下,它们可能不够直观和易用。为了解决这个问题,我们封装一个名为 TimeUtil 的时间处理类,通过提供一组易于使用的方法来简化常见的时间相关任务。在本博客文章中,我们将介绍 TimeUtil 的功能,并通过一些实际示例说明如何在各种场景中使用它。

功能

  • 时间的加减:TimeUtil 支持在 datetime 对象的基础上增加或减少年份、月份、天数、小时、分钟和秒。
  • 计算昨天、明天、一周后和一个月后的日期。
  • 将字符串转换为 datetime 对象。
  • 将 datetime 对象转换为字符串。
  • 将时间戳转换为字符串格式的时间。
  • 将字符串格式的时间转换为时间戳。
  • 将时间戳转换为 datetime 对象。
  • 两时间(datetime对象)之差
  • 计算工作日数

代码封装

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author: Hui
# @Desc: { 时间工具类模块 }
# @Date: 2022/11/26 16:08
import time
from datetime import datetime
from typing import Union
from dateutil.relativedelta import relativedelta
from enums import TimeFormatEnum, TimeUnitEnum
class TimeUtil(object):
    """时间工具类"""
    UNITS_IN_SECONDS = {
        TimeUnitEnum.DAYS: 86400,
        TimeUnitEnum.HOURS: 3600,
        TimeUnitEnum.MINUTES: 60,
        TimeUnitEnum.SECONDS: 1,
    }
    def __init__(self, datetime_obj: datetime = None, format_str: str = TimeFormatEnum.DateTime.value):
        """
        时间工具类初始化
        Args:
            datetime_obj: 待处理的datetime对象,不传时默认取当前时间
            format_str: 时间格式化字符串
        """
        self.datetime_obj = datetime_obj or datetime.now()
        self.format_str = format_str
    @property
    def yesterday(self) -> datetime:
        """获取昨天的日期"""
        return self.sub_time(days=1)
    @property
    def tomorrow(self) -> datetime:
        """获取明天的日期"""
        return self.add_time(days=1)
    @property
    def week_later(self) -> datetime:
        """获取一周后的日期"""
        return self.add_time(days=7)
    @property
    def month_later(self) -> datetime:
        """获取一个月后的日期"""
        return self.add_time(months=1)
    def add_time(self, years=0, months=0, days=0, hours=0, minutes=0, seconds=0, **kwargs) -> datetime:
        """增加指定时间"""
        return self.datetime_obj + relativedelta(
            years=years, months=months, days=days, hours=hours, minutes=minutes, seconds=seconds, **kwargs
        )
    def sub_time(self, years=0, months=0, days=0, hours=0, minutes=0, seconds=0, **kwargs) -> datetime:
        """减去指定时间"""
        return self.datetime_obj - relativedelta(
            years=years, months=months, days=days, hours=hours, minutes=minutes, seconds=seconds, **kwargs
        )
    def str_to_datetime(self, date_str: str, format_str: str = None) -> datetime:
        """将时间字符串转换为 datetime 对象"""
        format_str = format_str or self.format_str
        return datetime.strptime(date_str, format_str)
    def datetime_to_str(self, format_str: str = None) -> str:
        """将 datetime 对象转换为时间字符串"""
        format_str = format_str or self.format_str
        return self.datetime_obj.strftime(format_str)
    def timestamp_to_str(self, timestamp: float, format_str: str = None) -> str:
        """将时间戳转换为时间字符串"""
        format_str = format_str or self.format_str
        return datetime.fromtimestamp(timestamp).strftime(format_str)
    def str_to_timestamp(self, time_str: str, format_str: str = None) -> float:
        """将时间字符串转换为时间戳"""
        format_str = format_str or self.format_str
        return time.mktime(time.strptime(time_str, format_str))
    @staticmethod
    def timestamp_to_datetime(timestamp: float) -> datetime:
        """将时间戳转换为 datetime 对象"""
        return datetime.fromtimestamp(timestamp)
    @property
    def timestamp(self) -> float:
        """获取 datetime 对象的时间戳"""
        return self.datetime_obj.timestamp()
    def difference(self, other_datetime_obj: datetime, unit: Union[TimeUnitEnum, str] = TimeUnitEnum.DAYS) -> int:
        """
        计算两个日期之间的差值
        Args:
            other_datetime_obj: 另一个 datetime 对象
            unit: 时间单位
        Raises:
            ValueError: 如果传入unit不在枚举范围内,会抛出ValueError异常
        Returns:
            两个日期之间的差值,以指定的单位表示
        """
        if isinstance(unit, str):
            unit = TimeUnitEnum(unit)
        delta = abs(self.datetime_obj - other_datetime_obj)
        return int(delta.total_seconds() // self.UNITS_IN_SECONDS[unit])
    def difference_in_detail(self, datetime_obj: datetime):
        """
        计算两个日期之间的差值详情
        Args:
            datetime_obj: 时间对象
        Returns: DateDiff
        """
        delta = relativedelta(self.datetime_obj, datetime_obj)
        return DateDiff(
            years=abs(delta.years),
            months=abs(delta.months),
            days=abs(delta.days),
            hours=abs(delta.hours),
            minutes=abs(delta.minutes),
            seconds=abs(delta.seconds),
        )
    def count_weekdays_between(self, datetime_obj: datetime, include_end_date: bool = True) -> int:
        """计算两个日期之间的工作日数量
        Args:
            datetime_obj: datetime 对象
            include_end_date: 是否包含结束日期(默认为 True)
        Returns:
            两个日期之间的工作日数量
        """
        # 确保 start_date 是较小的日期,end_date 是较大的日期
        start_date = min(self.datetime_obj, datetime_obj)
        end_date = max(self.datetime_obj, datetime_obj)
        # 如果不包含结束日期,将 end_date 减去一天
        if not include_end_date:
            end_date = end_date - relativedelta(days=1)
        # 计算两个日期之间的天数
        days_between = abs((end_date - start_date).days)
        # 计算完整周数,每周有5个工作日
        weeks_between = days_between // 7
        weekdays = weeks_between * 5
        # 计算剩余的天数
        remaining_days = days_between % 7
        # 遍历剩余的天数,检查每天是否为工作日,如果是,则累加工作日数量
        for day_offset in range(remaining_days + 1):
            if (start_date + relativedelta(days=day_offset)).weekday() < 5:
                weekdays += 1
        return weekdays

示例Demo:

以下是使用 TimeUtil 库的一些示例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author: Hui
# @Desc: { 时间工具类案例 }
# @Date: 2023/04/30 21:08
import time
from datetime import datetime
from utils.time import TimeUtil
# 创建一个TimeUtil实例,默认使用当前时间
time_util = TimeUtil()
print("昨天的日期:", time_util.yesterday)
print("明天的日期:", time_util.tomorrow)
print("一周后的日期:", time_util.week_later)
print("一个月后的日期:", time_util.month_later)
>>>out
昨天的日期: 2023-04-29 21:10:56.642787
明天的日期: 2023-05-01 21:10:56.642787
一周后的日期: 2023-05-07 21:10:56.642787
一个月后的日期: 2023-05-30 21:10:56.642787

这里使用 property 装饰器让一些获取最近日期的方法使用起来变成获取属性值一样,使用起来变得更简洁。

?
1
2
3
4
5
6
7
# 从现在开始增加10天
print("10天后的日期:", time_util.add_time(days=10))
# 从现在开始减少5天
print("5天前的日期:", time_util.sub_time(days=5))
>>>out
10天后的日期: 2023-05-10 21:28:35.587173
5天前的日期: 2023-04-25 21:28:35.587173

add_time、sub_time 则是具体实现时间(datetime对象)加减运算的方法,主要就是通过 python-dateutil 库的 relativedelta 来封装,相比内置的 timedelta 来说可以更精准的计算年、月之差。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 将日期字符串转换为datetime对象
date_str = "2023-05-01 12:00:00"
print("字符串转换为datetime对象:", time_util.str_to_datetime(date_str))
# 将datetime对象转换为日期字符串
print("datetime对象转换为字符串:", time_util.datetime_to_str())
# 将时间戳转换为时间字符串
timestamp = time.time()
print("时间戳转换为时间字符串:", time_util.timestamp_to_str(timestamp))
# 将时间字符串转换为时间戳
time_str = "2023-05-01 12:00:00"
print("时间字符串转换为时间戳:", time_util.str_to_timestamp(time_str))
# 将时间戳转换为datetime对象
print("时间戳转换为datetime对象:", time_util.timestamp_to_datetime(timestamp))
# 获取当前时间的时间戳
print("当前时间的时间戳:", time_util.timestamp)
>>>out
字符串转换为datetime对象: 2023-05-01 12:00:00
datetime对象转换为字符串: 2023-04-30 21:28:35
时间戳转换为时间字符串: 2023-04-30 21:28:35
时间字符串转换为时间戳: 1682913600.0
时间戳转换为datetime对象: 2023-04-30 21:28:35.589926
当前时间的时间戳: 1682861315.587173

这块就是时间最常用的一些时间字符串、时间戳、datetime对象相互转换的方法。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 获取两个日期之间的差值
time_util = TimeUtil(datetime_obj=datetime(2023, 4, 24, 10, 30, 0))
datetime_obj = datetime(2023, 4, 29, 10, 30, 0)
delta_days = time_util.difference(datetime_obj, unit="days")
delta_hours = time_util.difference(datetime_obj, unit="hours")
delta_minutes = time_util.difference(datetime_obj, unit=TimeUnitEnum.MINUTES)
delta_seconds = time_util.difference(datetime_obj, unit=TimeUnitEnum.SECONDS)
print(f"两个日期之间相差的天数: {delta_days}")
print(f"两个日期之间相差的小时数: {delta_hours}")
print(f"两个日期之间相差的分钟数: {delta_minutes}")
print(f"两个日期之间相差的秒数: {delta_seconds}")
>>>out
两个日期之间相差的天数: 5
两个日期之间相差的小时数: 120
两个日期之间相差的分钟数: 7200
两个日期之间相差的秒数: 432000
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
date1 = datetime(2023, 4, 24# 2023年4月24日,星期一
date2 = datetime(2023, 5, 1# 2023年5月1日,星期一
time_util = TimeUtil(datetime_obj=date1)
# 计算两个日期之间的工作日数量
weekday_count = time_util.count_weekdays_between(date2, include_end_date=True)
print(f"从 {date1} 到 {date2} 之间有 {weekday_count} 个工作日。(包含末尾日期)")
weekday_count = time_util.count_weekdays_between(date2, include_end_date=False)
print(f"从 {date1} 到 {date2} 之间有 {weekday_count} 个工作日。(不包含末尾日期)")
date_diff = time_util.difference_in_detail(date2)
print(date_diff)
>>>out
2023-04-24 00:00:00 2023-05-01 00:00:00 之间有 6 个工作日。(包含末尾日期)
2023-04-24 00:00:00 2023-05-01 00:00:00 之间有 5 个工作日。(不包含末尾日期)
DateDiff(years=0, months=0, days=7, hours=0, minutes=0, seconds=0)

最后就是根据两时间对象计算计算差值,计算工作日数量等。

感悟

一开始我想把时间工具类像excel工具类一样封装类方法来调用,后面发现好多方法都要共用datetime对象和格式化字符串,于是就封装成了实例对象操作方式,简化了传参方式。

使用实例对象操作的优势:

  • 可以通过对象保存状态,例如在初始化时可以传入一个特定的datetime对象或时间格式字符串,这样在其他方法中可以直接使用。
  • 更容易扩展和添加新功能。如果需要添加新的成员变量或方法,可以直接在类中进行,而无需改变已有的静态方法。

使用类对象操作类方法的优势:

  • 代码更简洁,不需要创建类的实例,可以直接调用静态方法。
  • 在某些情况下,静态方法可能执行速度更快,因为它们不需要创建实例对象。

总之,根据你的需求和编程风格来选择使用实例对象操作还是类对象操作类、静态方法。

虽然通过实例化时间工具类会比类对象直接操作静态方法更浪费内存开销,但让这个工具类单例化,就可以减少创建对象的开销。具体单例化可查看源代码,这里就不细说了。

源代码

HuiDBK/py-tools: 打造 Python 开发常用的工具,让Coding变得更简单 (github.com)

以上就是封装 Python 时间处理库创建自己的TimeUtil类示例的详细内容,更多关于封装 Python TimeUtil类的资料请关注服务器之家其它相关文章!

原文链接:https://juejin.cn/post/7227839676463300669

延伸 · 阅读

精彩推荐
  • Python使用python绘制二元函数图像的实例

    使用python绘制二元函数图像的实例

    今天小编就为大家分享一篇使用python绘制二元函数图像的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    阳光伴我们成长9242021-05-27
  • Python简单谈谈Python中的json与pickle

    简单谈谈Python中的json与pickle

    下面小编就为大家带来一篇简单谈谈Python中的json与pickle。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    Python教程网3592020-11-27
  • Pythonpython Django模板的使用方法

    python Django模板的使用方法

    这篇文章主要为大家介绍了python Django模板的使用方法,代码很详细,感兴趣的小伙伴们可以参考一下 ...

    Python教程网2802020-08-06
  • Pythonpython机器学习之神经网络(二)

    python机器学习之神经网络(二)

    这篇文章主要为大家详细介绍了python机器学习之神经网络第二篇,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    Jeffrey_Cui12222020-12-26
  • Python基于Python实现开心消消乐小游戏的示例代码

    基于Python实现开心消消乐小游戏的示例代码

    这篇文章主要是带着大家自制一款开心消消乐,还原度超高哦~还在等什么动动手就能拥有属于自己的”消消乐“小游戏呢,赶快学起来吧...

    魔王不会哭9622023-02-15
  • Python详解python时间模块中的datetime模块

    详解python时间模块中的datetime模块

    这篇文章主要为大家介绍了python时间模块中的datetime模块,datetime模块的接口则更直观、更容易调用,想要了解datetime模块的朋友可以参考一下 ...

    crazyhacking4662020-08-06
  • Pythonpython版DDOS攻击脚本

    python版DDOS攻击脚本

    这篇文章主要为大家详细介绍了python版DDOS攻击脚本,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    一把汤勺9102021-07-11
  • PythonPython 如何输出百分比

    Python 如何输出百分比

    这篇文章主要介绍了Python 如何输出百分比,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小...

    爱博客大伯44962020-07-31