当前位置:

首页 > 编程开发 > 如何根据时间处理库封装自己的Python TimeUtil类?

如何根据时间处理库封装自己的Python TimeUtil类?

简介在日常的Python开发中,处理时间和日期的需求是非常常见的。尽管Python内置了datetime和time模块,但在某些情况下,它们可能不够直观和易用。为了解决这个问题,我们封装一个名为TimeUtil的时间处理类,通过提供一组易于使用的方法来简化常见的时间相关任务。功能时间的加减:TimeUtil支持在datetime对象的基础上增加或减少年份、月份、天数、小时、分钟和秒。计算昨天、明天、一周后和一个月后的日期。将字符串转换为datetime对象。将datetime对象转换为字符串。将时间戳转换

本文目录

    简介

    在日常的Python开发中,处理时间和日期的需求是非常常见的。尽管Python内置了 datetime 和 time 模块,但在某些情况下,它们可能不够直观和易用。为了解决这个问题,我们封装一个名为 TimeUtil 的时间处理类,通过提供一组易于使用的方法来简化常见的时间相关任务。

    功能

    • 时间的加减:TimeUtil 支持在 datetime 对象的基础上增加或减少年份、月份、天数、小时、分钟和秒。

    • 计算昨天、明天、一周后和一个月后的日期。

    • 将字符串转换为 datetime 对象。

    • 将 datetime 对象转换为字符串。

    • 将时间戳转换为字符串格式的时间。

    • 将字符串格式的时间转换为时间戳。

    • 将时间戳转换为 datetime 对象。

    • 两时间(datetime对象)之差

    • 计算工作日数

    代码封装

    #!/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 库的一些示例:

    #!/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 装饰器让一些获取最近日期的方法使用起来变成获取属性值一样,使用起来变得更简洁。

    # 从现在开始增加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 来说可以更精准的计算年、月之差。

    # 将日期字符串转换为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对象相互转换的方法。

    # 获取两个日期之间的差值
    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
    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)

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

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Python
    相关文章 更多
    python删除一个列表里的重复元素的方法与代码示例
    python删除一个列表里的重复元素的方法与代码示例

    学习如何使用Python高效删除列表中的重复元素。本文提供5种常见方法的代码示例,涵盖保持顺序与不保持顺序的场景,适合初学者和进阶开发者参考。

    Python写接口的步骤及完整代码示例
    Python写接口的步骤及完整代码示例

    详细讲解使用Python编写Web接口的核心步骤与完整代码示例,涵盖环境准备、路由定义、数据校验、服务启动及调试测试方法。

    codex怎么读取word文档及docx文件操作教程
    codex怎么读取word文档及docx文件操作教程

    介绍如何利用编程工具读取和解析Word文档(docx格式),涵盖基础文本提取代码示例、结构化数据处理逻辑,以及处理复杂排版时的技术局限与替代方案。

    怎么在Python中调用C语言代码提升性能
    怎么在Python中调用C语言代码提升性能

    详细讲解在Python中调用C语言代码提升性能的完整实践指南,包含原理分析、编译步骤、ctypes与CFFI具体实现、性能对比及常见陷阱。

    Python与C语言的性能差异及底层原理
    Python与C语言的性能差异及底层原理

    深入解析Python与C语言在执行效率上的数量级差异,从编译机制、变量内存布局、动态类型推断到GIL锁,系统阐明底层核心原理。

    Python和C语言哪个更适合编程入门
    Python和C语言哪个更适合编程入门

    客观对比Python与C语言在心智负担、底层机制与学习反馈上的核心差异,提供清晰有据的选择标准与切实的入门学习路径。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

    langgraph python guide中文入门教程详解
    langgraph python guide中文入门教程详解

    本篇LangGraph Python中文入门教程详解,系统梳理StateGraph状态机定义、节点编写、边与条件路由、检查点持久化(MemorySaver)等核心机制,提供从环境安装到完整循环智能体构建的代码示例与实操指导。

    Windows 安装 Python:从官方入口到虚拟环境的可复现实践
    Windows 安装 Python:从官方入口到虚拟环境的可复现实践

    面向后端开发者,基于 Python 官方文档说明如何在 Windows 上安装 Python、创建 venv 虚拟环境及使用 pip 管理依赖。包含可复制命令、验证方法及工具选择边界,避免常见配置误区。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。