Python Excel日期格式化:datetime写进xlsx并显示成yyyy-mm-dd
用openpyxl把datetime对象写进Excel单元格,再用number_format控制显示成yyyy-mm-dd或yyyy年m月d日,避免日期变成数字或文本。
场景痛点
Python 里拼出来的日期,直接 ws["A1"] = "2026-09-14" 写进去,Excel 当成文本,不能排序不能做日期计算;写成 46000 这种数字又看不懂。正确做法是写 datetime 对象,再套日期格式串,Excel 既能识别成日期、又能按你要的样式显示。
用到的库
pip install openpyxl
完整代码
from datetime import datetime, date
from openpyxl import load_workbook
def demo_date_format(file_path: str) -> None:
wb = load_workbook(file_path)
ws = wb.active
# 1) 写一个 datetime 对象到单元格
ws["A1"] = datetime(2026, 9, 14, 10, 30, 0)
# 显示成 2026-09-14 10:30
ws["A1"].number_format = "yyyy-mm-dd hh:mm"
# 2) 写一个纯日期
ws["A2"] = date(2026, 9, 14)
ws["A2"].number_format = "yyyy-mm-dd"
# 3) 中文样式
ws["A3"] = date(2026, 9, 14)
ws["A3"].number_format = 'yyyy"年"m"月"d"日"'
# 4) 从字符串解析后再写入,避免变成文本
raw = "2026/9/14 18:00"
parsed = datetime.strptime(raw, "%Y/%m/%d %H:%M")
ws["A4"] = parsed
ws["A4"].number_format = "yyyy-mm-dd hh:mm"
# 5) 整列日期格式:找"日期"列,逐行套格式
header = [c.value for c in ws[1]]
if "日期" in header:
col = header.index("日期") + 1
for row in range(2, ws.max_row + 1):
cell = ws.cell(row=row, column=col)
# 如果该格写的是字符串,先尝试转成 datetime
if isinstance(cell.value, str):
for fmt in ("%Y-%m-%d", "%Y/%m/%d", "%Y.%m.%d"):
try:
cell.value = datetime.strptime(cell.value, fmt)
break
except ValueError:
continue
if isinstance(cell.value, datetime):
cell.number_format = "yyyy-mm-dd"
wb.save(file_path)
print("日期格式已应用")
if __name__ == "__main__":
demo_date_format(r"D:\reports\销售明细.xlsx")
代码讲解
- 写日期一定要传
datetime.datetime或datetime.date对象,不要传字符串;openpyxl 会自动按 Excel 的日期序列号存。 number_format里yyyy是 4 位年、mm是月、dd是日、hh是 24 小时制小时、ss是秒。- 中文样式用引号把中文字符包起来:
'yyyy"年"m"月"d"日"',否则 Excel 会把年当成格式字母解析。 datetime.strptime(raw, "%Y/%m/%d %H:%M")把字符串解析成 datetime,再写进单元格,这是处理外部脏数据的常用步骤。- 最后一段把已经是字符串的「日期」列逐格尝试解析成 datetime,再套格式,处理的是历史表里日期本来就是文本的情况。
运行结果
打开文件,A1 显示 2026-09-14 10:30,A2 显示 2026-09-14,A3 显示 2026年9月14日,A4 显示 2026-09-14 18:00;「日期」列原来的文本日期也被识别成真正的日期,可排序可筛选。
注意事项
- 日期在 Excel 底层是从 1900-01-01 开始的序列号,
46000这种数字本质上就是日期,套上yyyy-mm-dd格式就能正常显示。 - 不要把
mm和MM搞混:Excel 格式里mm是月,MM在代码里无所谓,但格式串里小写mm才是月,大写会被当成分钟。 - 跨时区/跨年的日期字符串解析失败时,先
print(repr(s))看清楚原始格式,再写对应的strptime模板。 - 读 openpyxl 出来的日期值是
datetime对象,写回时保持datetime不要转字符串,否则又退回文本。 - 日期格式和数字格式共用
number_format,写在同一个属性上,不会互相冲突。

更新时间:2026-09-15 09:10:41
上一篇:Python Excel数据去重 pandas drop_duplicates