科技奇趣|为什么 Excel 认为 1900 年是闰年?

简介: 实际上 1900 年不是闰年,没有 2 月 29 日,所以很明显 这是 Excel 的一个 Bug。

我们先来看一下现象:

图片

实际上 1900 年不是闰年,没有 2 月 29 日,所以很明显 这是 Excel 的一个 Bug

发现

我之所以会留意到这个,是因为最近在做一个绩效核对的小工具,需要用 Python 读取和处理销售交上来的 Excel。

销售交上来的东西总是稀奇古怪,比如有一列是要填日期,交上来的表格里,有的读出来是日期类型,有的读出来是字符串类型,这都还好说,日期类型直接用,字符串按格式解析成日期,就好了。但这天发现有个销售交上来的表格里,这一列读出来是数字类型。

比如 2024-02-01,读出来对应数字 45323

怎么将这个数字转换成日期呢?

首先搜索了微软的官方文档,找到关于 Date systems in Excel 的说明:

Excel supports two date systems, the 1900 date system and the 1904 date system. Each date system uses a unique starting date from which all other workbook dates are calculated. All versions of Excel for Windows calculate dates based on the 1900 date system. Excel 2008 for Mac and earlier Excel for Mac versions calculate dates based on the 1904 date system. Excel 2016 for Mac and Excel for Mac 2011 use the 1900 date system, which guarantees date compatibility with Excel for Windows.
...
In the 1900 date system, dates are calculated by using January 1, 1900, as a starting point. When you enter a date, it is converted into a serial number that represents the number of days elapsed since January 1, 1900.

就是说,除了 Excel for Mac 的早期版本外,都是默认采用 1900 date system,以 1900-01-01 作为起点(第 1 天)。

于是根据这个信息写一个函数来将数字转换成日期,但是 翻车了……

from datetime import datetime, timedelta

def int_to_date(s):
    date_zero = datetime(1900, 1, 1)
    delta = timedelta(days = s - 1)
    return date_zero + delta

print(int_to_date(45323))

# 输出 2024-02-02 00:00:00

Excel 表格里是 2024-02-01,读出来是 45323,咋按 1900-01-01 作为第一天,反算出来 45323 却是 2024-02-02 了呢?

探究

于是一番搜索,先是找到了 OpenOffice 论坛里的讨论 Why the base date is 1899-12-30 instead of 1899-12-31?,里面有如下信息:

The earliest date Excel handles sensibly is 1900-01-01, which is "day 1" (not zero). This makes "Excel epoch" (day zero) 1899-12-31. However, Excel inherited an error from previous spreadsheet apps which assumed that 1900 was a leap year. The nonexistent 29th of February 1900 is counted in Excel time spans, just like it used to be in Lotus 123 and (IIRC) SuperCalc, and probably in most other relevant spreadsheet apps.

有意思了……于是继续在维基百科的 Microsoft Excel 词条上找到了佐证信息:

Excel的时间系统中,会认为1900年2月29日是有效日期,也就是1900年为闰年,但实际上并不是。这是源于模仿早期竞品Lotus 1-2-3上的缺陷而引入的特性,由于Lotus 1-2-3的时间纪元以1900年起始,之后的时间为差值累加,导致其时间体系一开始就认为1900年是闰年,而Excel为了兼容Lotus 1-2-3的文件格式,也保留了这个缺陷作为特性而不进行修复,即使至今最新版本已不需要兼容Lotus 1-2-3。

里面还给出了微软官方的相关解释链接:Excel incorrectly assumes that the year 1900 is a leap year,并且讲述了 Excel 的发展历史,挺有趣的,可以一读。

至此,就破案了。

数字到日期的换算

我们上面提供的数字到日期的换算的方案,做个小修正就能使用了:

from datetime import datetime, timedelta

def int_to_date(s):
    date_zero = datetime(1899, 12, 30)
    delta = timedelta(days = s)
    return date_zero + delta

print(int_to_date(45323))

# 输出 2024-02-01 00:00:00

当然这个程序并不完美,比如计算 60 以内的数字,算出来的就与 Excel 上显示的日期不一致,但 who cares……毕竟 Excel 上有 1900-02-29 这种你永远不会用到的日期 😆

参考链接

目录
相关文章
|
存储 监控 API
【年终特辑】看见科技创新力量 洞见时代创业精神—企业服务—Vika:目标是取代办公场景下的Excel
【年终特辑】看见科技创新力量 洞见时代创业精神—企业服务—Vika:目标是取代办公场景下的Excel
|
26天前
|
数据采集 数据可视化 数据挖掘
利用Python自动化处理Excel数据:从基础到进阶####
本文旨在为读者提供一个全面的指南,通过Python编程语言实现Excel数据的自动化处理。无论你是初学者还是有经验的开发者,本文都将帮助你掌握Pandas和openpyxl这两个强大的库,从而提升数据处理的效率和准确性。我们将从环境设置开始,逐步深入到数据读取、清洗、分析和可视化等各个环节,最终实现一个实际的自动化项目案例。 ####
|
2月前
|
数据采集 存储 JavaScript
自动化数据处理:使用Selenium与Excel打造的数据爬取管道
本文介绍了一种使用Selenium和Excel结合代理IP技术从WIPO品牌数据库(branddb.wipo.int)自动化爬取专利信息的方法。通过Selenium模拟用户操作,处理JavaScript动态加载页面,利用代理IP避免IP封禁,确保数据爬取稳定性和隐私性。爬取的数据将存储在Excel中,便于后续分析。此外,文章还详细介绍了Selenium的基本设置、代理IP配置及使用技巧,并探讨了未来可能采用的更多防反爬策略,以提升爬虫效率和稳定性。
164 4
|
2天前
|
存储 Java easyexcel
招行面试:100万级别数据的Excel,如何秒级导入到数据库?
本文由40岁老架构师尼恩撰写,分享了应对招商银行Java后端面试绝命12题的经验。文章详细介绍了如何通过系统化准备,在面试中展示强大的技术实力。针对百万级数据的Excel导入难题,尼恩推荐使用阿里巴巴开源的EasyExcel框架,并结合高性能分片读取、Disruptor队列缓冲和高并发批量写入的架构方案,实现高效的数据处理。此外,文章还提供了完整的代码示例和配置说明,帮助读者快速掌握相关技能。建议读者参考《尼恩Java面试宝典PDF》进行系统化刷题,提升面试竞争力。关注公众号【技术自由圈】可获取更多技术资源和指导。
|
4月前
|
关系型数据库 MySQL Shell
不通过navicat工具怎么把查询数据导出到excel表中
不通过navicat工具怎么把查询数据导出到excel表中
55 0
|
2月前
|
数据处理 Python
Python实用记录(十):获取excel数据并通过列表的形式保存为txt文档、xlsx文档、csv文档
这篇文章介绍了如何使用Python读取Excel文件中的数据,处理后将其保存为txt、xlsx和csv格式的文件。
122 3
Python实用记录(十):获取excel数据并通过列表的形式保存为txt文档、xlsx文档、csv文档
|
2月前
|
easyexcel Java UED
SpringBoot中大量数据导出方案:使用EasyExcel并行导出多个excel文件并压缩zip后下载
在SpringBoot环境中,为了优化大量数据的Excel导出体验,可采用异步方式处理。具体做法是将数据拆分后利用`CompletableFuture`与`ThreadPoolTaskExecutor`并行导出,并使用EasyExcel生成多个Excel文件,最终将其压缩成ZIP文件供下载。此方案提升了导出效率,改善了用户体验。代码示例展示了如何实现这一过程,包括多线程处理、模板导出及资源清理等关键步骤。
|
3月前
|
数据采集 存储 数据挖掘
使用Python读取Excel数据
本文介绍了如何使用Python的`pandas`库读取和操作Excel文件。首先,需要安装`pandas`和`openpyxl`库。接着,通过`read_excel`函数读取Excel数据,并展示了读取特定工作表、查看数据以及计算平均值等操作。此外,还介绍了选择特定列、筛选数据和数据清洗等常用操作。`pandas`是一个强大且易用的工具,适用于日常数据处理工作。
|
4月前
|
SQL JSON 关系型数据库
n种方式教你用python读写excel等数据文件
n种方式教你用python读写excel等数据文件
|
4月前
|
存储 Java Apache