日期和时间编程指南

在数据科学和编程领域,处理日期和时间数据是一项极具挑战性的任务。这不仅涉及到不同的日期格式、时区差异、夏令时调整等复杂因素,还涉及到如何准确地引用特定的日期和时间。幸运的是,Python内置的datetime模块为提供了强大的支持,帮助应对这些挑战。

为何日期和时间编程如此困难

编程处理日期和时间之所以困难,是因为计算机程序偏好有序且规律的事件处理方式,而人类使用日期和时间的方式往往是无序和不规则的。例如,美国和加拿大实行的夏令时就是一个典型的例子。他们在三月的第二个星期日将时钟向前调整一小时,在十一月的第一个星期日再向后调整一小时。

如果项目中需要考虑时区,情况可能会变得更加复杂。理想情况下,时区应该沿着经度线直线划分,但由于政治和历史原因,这些分界线很少是直线。

标准日期格式

不同文化使用不同的日期格式,如D M YY M DM D Y。如果没有标准化的格式,将会造成混乱。因此,国际标准化组织(ISO)制定了ISO 8601标准,定义了一个统一的格式以避免混淆。根据该格式,约定是从最重要的数字到最不重要的数字。因此,格式为:YYYY-MM-DD hh:mm:ss

计算机如何测量时间

大多数计算机从称为Unix纪元的任意瞬间开始计时。这个任意日期是1970年1月1日,UTC时间00:00:00。协调世界时(UTC)指的是0°经度的时间,也就是众所周知的GMT或格林尼治子午线时间。它不调整夏令时,因此每天始终保持24小时。

Unix时间以1970年1月1日以来的秒数来测量。可以用几行Python代码轻松查看当前的Unix时间。

>>> import datetime >>> print(datetime.datetime.now().timestamp()) 1620566182.766565

这意味着自1970年1月1日以来,已经过去了1620566182.766565秒,当写这篇博客的时候!这里有一个关于Unix时间的有趣事实。由于大多数旧操作系统是32位的,它们以32位有符号整数存储Unix时间。

如果熟悉Y2K问题,就会知道这个问题的走向。以32位有符号整数格式存储意味着在2038年1月19日03:14:07,整数将溢出,导致所谓的2038年问题,或通常称为Y2038。为了避免对关键系统造成灾难性后果,这个问题需要尽快解决。

datetime模块

datetime模块是Python内置的,因此无需单独安装。只需将其导入到代码中,就可以开始使用了。

该模块提供了不同的类来处理日期、时间和时间间隔。两个主要的对象是datedatetime。这些类有6种类型,这里是它们的官方描述:

  1. datetime.date:用于操作日期,不涉及时间。属性包括yearmonthday
  2. datetime.time:用于操作时间,不涉及日期,假设每天正好有24*3600秒。属性包括hourminutesecondmicrosecondtzinfo
  3. datetime.datetime:用于操作日期和时间的组合。属性包括yearmonthdayhourminutesecondmicrosecondtzinfo
  4. datetime.timedelta:两个日期、时间或datetime对象之间的持续时间,分辨率可达微秒。
  5. datetime.tzinfo:这是一个抽象基类,用于时区对象。可以由datetime和time类使用,以提供可定制的时间调整概念(例如,考虑时区和/或夏令时)。
  6. datetime.timezone:tzinfo抽象基类的实现。

可以在这里阅读更多关于这些类的深入信息。现在让开始编码吧!

创建DateTime对象

可以使用ISO格式创建一个datetime对象。

from datetime import datetime a = datetime(2021, 5, 9, 13, 13, 6) print(a) # 输出: 2021-05-09 13:13:06

要获取当前日期:

today = datetime.now() print(today) # 输出: 2021-05-10 16:28:05 print(type(today)) # 输出: <class 'datetime.datetime'>

因此,today确实是一个datetime对象。以下是datetime类的一些有用方法。

dt_nw = datetime.now() # 从datetime获取小时 print('Hour: ', dt_nw.hour) # 输出: Hour: 16 # 从datetime获取分钟 print('Minute: ', dt_nw.minute) # 输出: Minute: 28

可以使用成员函数.weekday()获取一周中的某一天的名称,然后使用另一个名为calendar的模块将其转换为字符串格式(即星期一、星期二、星期三……)。首先,将导入Calendar模块,然后使用一些有用的操作。

import calendar my_date = datetime.now() # 从日期获取月份 print('Month: ', my_date.month) # 输出: Month: 5 # 从日期获取年份 print('Year: ', my_date.year) # 输出: Year: 2021 # 从日期获取月份中的一天 print('Day of Month:', my_date.day) # 输出: Day of Month: 10 # 从日期获取一周中的某一天(数字) print('Day of Week (number): ', my_date.weekday()) # 输出: Day of Week (number): 0 # 从日期获取一周中的某一天(名称) print('Day of Week (name): ', calendar.day_name[my_date.weekday()]) # 输出: Day of Week (name): Monday

处理时区

Date和Time对象可以分为两大类,主要是“Aware”和“Naive”。简单来说,如果一个对象包含时区信息,它就是Aware的,否则就是Naive的。Aware对象如datetime、date和time有一个额外的可选属性,叫做tzinfo。但tzinfo本身是一个抽象类。要处理这些,需要确切知道需要哪些方法。处理时区问题可以通过pytz模块来简化。使用这个模块,可以处理使用夏令时的地点的夏令时,并进行跨时区转换。

from pytz import timezone # 创建UTC时区 utc = timezone('UTC') # 本地化日期和时间 loc = utc.localize(datetime(2020, 5, 10, 17, 41, 0)) print(loc) # 输出: 2020-05-10 17:41:00+00:00 # 将本地化日期和时间转换为Asia/Dhaka时区 dhaka = timezone("Asia/Dhaka") print(loc.astimezone(dhaka)) # 输出: 2020-05-10 23:41:00+06:00 # 将本地化日期和时间转换为Europe/Berlin时区 berlin = timezone('Europe/Berlin') print(loc.astimezone(berlin)) # 输出: 2020-05-10 19:41:00+02:00

localize()函数用于给datetime对象添加一个时区位置。astimezone()函数用于将当前时区转换为其他指定的时区。

时间差或时间段

有时在编程时,需要找到某项任务的剩余时间,或指定某种时间段。这时timedelta对象就派上用场了。在大多数科学术语中,delta意味着两个事物之间的差异。可以使用它来相互加减日期和时间。以下是如何操作的:

from datetime import timedelta # 获取当前时间 now = datetime.now() print("Today's date & time: ", str(now)) # 输出: Today's date & time: 2021-05-10 12:56:08.979894 # 在当前日期上加上365天 future_date_after_one_year = now + timedelta(days=365) print('Date & time after one year: ', future_date_after_one_year) # 输出: Date & time after one year: 2022-05-10 12:56:08.979894 # 从当前日期减去7天 seven_days_ago = now - timedelta(days=7) print('Date & time seven days ago: ', seven_days_ago) # 输出: Date & time seven days ago: 2021-05-03 12:56:08.979894

使用strftime()和strptime()格式化日期

datetime、date和time对象都支持strftime()方法,将对象转换为特定格式的字符串。相反的操作是使用datetime.strptime()方法,从字符串创建datetime对象。

from datetime import datetime date_str = "10 May, 2021" # 格式化日期 date_obj = datetime.strptime(date_str, "%d %B, %Y") print("Today's date is: ", date_obj) # 输出: Today's date is: 2021-05-10 00:00:00 # 当前日期和时间 now = datetime.now() # 格式化时间为HH:MM:SS time = now.strftime("%H:%M:%S") print("Time:", time) # 输出: Time: 14:05:55 # 格式化日期和时间 date_time = now.strftime("%m/%d/%Y, %H:%M:%S") print("Date and Time:", date_time) # 输出: Date and Time: 05/10/2021, 14:05:55

在处理时间数据或时间序列时,通常需要处理时间戳。可以使用datetime.timestamp()将数据存储为Unix时间戳格式。

# 获取当前日期 now = datetime.now() # 将当前日期转换为时间戳 timestamp = datetime.timestamp(now) print("Date and Time :", now) # 输出: Date and Time : 2021-05-10 14:17:54.739358 print("Timestamp:", timestamp) # 输出: Timestamp: 1620656274.739358

同样,可以从时间戳获取日期和时间对象:

timestamp = 1620656274.739358 # 将时间戳转换为datetime对象 date_obj = datetime.fromtimestamp(timestamp) print("Today's date & time:", date_obj) # 输出: Today's date & time: 2021-05-10 14:17:54.739358

Pandas可以被称为任何数据科学项目的支柱之一。它使得处理日期和时间对象变得更加容易。在处理DataFrame时,to_datetime()函数可以方便地将文本和字符串转换为Pythondatetime对象。

import pandas as pd # 使用to_datetime()函数创建日期对象 date = pd.to_datetime("10th of May, 2021") print(date) # 输出: 2021-05-10 00:00:00
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485