在 XlsxWriter 中处理日期和时间

Excel 用实数表示日期和时间。例如,2013 年 1 月 1 日中午 12 点对应数字 41275.5。整数部分保存从日期系统起点开始的天数,小数部分表示一天中已经过去的比例。

Excel 中的日期或时间本质上与其他数字一样。要以日期形式显示,必须应用 Excel 数字格式。下面用同一个数字展示不同格式:

import xlsxwriter

workbook = xlsxwriter.Workbook('date_examples.xlsx')
worksheet = workbook.add_worksheet()

# Widen column A for extra visibility.
worksheet.set_column('A:A', 30)

# A number to convert to a date.
number = 41333.5

# Write it as a number without formatting.
worksheet.write('A1', number)                # 41333.5

format2 = workbook.add_format({'num_format': 'dd/mm/yy'})
worksheet.write('A2', number, format2)       # 28/02/13

format3 = workbook.add_format({'num_format': 'mm/dd/yy'})
worksheet.write('A3', number, format3)       # 02/28/13

format4 = workbook.add_format({'num_format': 'd-m-yyyy'})
worksheet.write('A4', number, format4)       # 28-2-2013
format5 = workbook.add_format({'num_format': 'dd/mm/yy hh:mm'})
worksheet.write('A5', number, format5)       # 28/02/13 12:00

format6 = workbook.add_format({'num_format': 'd mmm yyyy'})
worksheet.write('A6', number, format6)       # 28 Feb 2013

format7 = workbook.add_format({'num_format': 'mmm d yyyy hh:mm AM/PM'})
worksheet.write('A7', number, format7)       # Feb 28 2013 12:00 PM

workbook.close()

原文示例:同一个数字应用不同日期格式

为了简化日期和时间处理,XlsxWriter 提供 write_datetime(),用于写入 Python 标准库 datetime 对象。它支持 datetime.datetime、datetime.date、datetime.time 和 datetime.timedelta。

创建日期时间对象有多种方法,例如 datetime.datetime.strptime():

date_time = datetime.datetime.strptime('2013-01-23', '%Y-%m-%d')

其他创建方法参见 Python datetime 文档。与前面一样,还需要创建并应用数字格式:

date_format = workbook.add_format({'num_format': 'd mmmm yyyy'})
worksheet.write_datetime('A1', date_time, date_format)

# Displays "23 January 2013"

下面是更完整的示例,以多种格式显示相同的日期时间:

from datetime import datetime
import xlsxwriter

# Create a workbook and add a worksheet.
workbook = xlsxwriter.Workbook('datetimes.xlsx')
worksheet = workbook.add_worksheet()
bold = workbook.add_format({'bold': True})

# Expand the first columns so that the dates are visible.
worksheet.set_column('A:B', 30)

# Write the column headers.
worksheet.write('A1', 'Formatted date', bold)
worksheet.write('B1', 'Format', bold)

# Create a datetime object to use in the examples.

date_time = datetime.strptime('2013-01-23 12:30:05.123',
                              '%Y-%m-%d %H:%M:%S.%f')

# Examples date and time formats.
date_formats = (
    'dd/mm/yy',
    'mm/dd/yy',
    'dd m yy',
    'd mm yy',
    'd mmm yy',
    'd mmmm yy',
    'd mmmm yyy',
    'd mmmm yyyy',
    'dd/mm/yy hh:mm',
    'dd/mm/yy hh:mm:ss',
    'dd/mm/yy hh:mm:ss.000',
    'hh:mm',
    'hh:mm:ss',
    'hh:mm:ss.000',
)

# Start from first row after headers.
row = 1

# Write the same date and time using each of the above formats.
for date_format_str in date_formats:

    # Create a format for the date or time.
    date_format = workbook.add_format({'num_format': date_format_str,
                                      'align': 'left'})

    # Write the same date using different formats.
    worksheet.write_datetime(row, 0, date_time, date_format)

    # Also write the format string for comparison.
    worksheet.write_string(row, 1, date_format_str)

    row += 1

workbook.close()

原文示例:日期时间值与格式字符串的对照

默认日期格式

某些情况下,希望写入日期时间对象时使用默认格式,例如通过 write_row() 处理一整行数据。可以在 Workbook() 构造函数中设置 default_date_format:

workbook = xlsxwriter.Workbook('datetimes.xlsx', {'default_date_format':
                                                  'dd/mm/yy'})
worksheet = workbook.add_worksheet()
date_time = datetime.now()
worksheet.write_datetime(0, 0, date_time)  # Formatted as 'dd/mm/yy'

workbook.close()

时区处理

Excel 的日期时间不支持时区,因此 XlsxWriter 无法保证把带时区的 Python 日期时间对象无歧义地映射为 Excel 日期时间。应根据实际需求处理时区。通常先换算到所需时区,再移除对象的 tzinfo,之后传入 write_datetime():

utc_datetime = datetime(2016, 9, 23, 14, 13, 21, tzinfo=utc)
naive_datetime = utc_datetime.replace(tzinfo=None)

worksheet.write_datetime(row, 0, naive_datetime, date_format)

也可以使用 Workbook() 的 remove_timezone 选项,从传给 write_datetime() 的值中去掉时区。该选项默认为 False,启用方式如下:

workbook = xlsxwriter.Workbook(filename, {'remove_timezone': True})

结合 Pandas 与 XlsxWriter 使用时,原文给出以下传参方式:

writer = pd.ExcelWriter('pandas_example.xlsx',
                        engine='xlsxwriter',
                        options={'remove_timezone': True})

Pandas 版本补充

上述 options= 是原文保留的写法。当前 Pandas 3.0 的 ExcelWriter API 使用 engine_kwargs 向引擎传参,对应形式为 engine_kwargs={"options": {"remove_timezone": True}}。这只把配置传递给 XlsxWriter;时区换算仍应在导出前按业务含义完成,不能把去掉时区等同于时区转换。


来源:Working with Dates and Time,XlsxWriter 文档。本文为中文翻译,代码和两张原文示例图保留原样。

Copyright © 2013–2025, John McNamara jmcnamara@cpan.org。采用 BSD 两条款许可。允许以源代码或二进制形式再分发和使用,无论是否修改,但须满足:源代码再分发保留上述版权声明、条件与下列免责声明;二进制再分发在随附文档和/或其他材料中重现上述版权声明、条件与下列免责声明。

本软件由版权持有人和贡献者按原样提供,不作任何明示或默示保证,包括但不限于适销性和特定用途适用性。无论依据合同、严格责任或侵权(包括过失或其他原因),版权持有人和贡献者均不对因使用本软件而产生的任何直接、间接、附带、特殊、惩罚性或后果性损失负责,包括采购替代商品或服务、使用损失、数据损失、利润损失或业务中断,即使已被告知可能发生此类损失。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容