엑셀 날짜 차이가 4년이다: 먼저 통합 문서 날짜 체계를 살펴보자
iso_dates는 파일의 날짜 직렬화 방법을 제어하며 메모리의 날짜/시간을 자동으로 문자열로 변환하지 않습니다. 날짜 일련 번호에는 통합 문서의 시대가 필요합니다. 여기서는 두 날짜 시스템을 비교하고 저장된 XML 및 다시 읽기 값을 확인합니다.
Excel은 4년 단위로 오프셋된 날짜를 내보내는데, 대부분의 경우 문제는 데이터 자체가 아니라 통합 문서의 날짜 시스템에 있습니다. 보고서 내보내기, ETL 스크립트 또는 Excel 파일의 플랫폼 간 교환을 담당하는 개발자 및 데이터 담당자를 위해 작성되었습니다. 전반적인 날짜 이동, 날짜로 표시할 수 없는 숫자, 1900년경의 데이터 이상 등의 상황이 발생하는 경우 먼저 이 문서의 순서에 따라 문제를 해결할 수 있습니다.
이 글을 읽고 나면 1900년과 1904년의 두 날짜 체계의 차이점을 이해하고, 현재 통합 문서에서 사용하는 체계를 확인하기 위해 workbook.epoch를 읽는 방법을 알게 되며, XML을 확인하고 저장 후 값을 다시 읽는 수용 방법을 마스터하게 됩니다. 이 문서의 코드와 표는 실제 문서로 작업하기 전 체크리스트로 적합한 합성 샘플로 설명되어 있습니다.
엑셀 날짜가 4년 다르다면 어떻게 해야 하나요? 한 문장 결론
먼저 통합 문서의 workbook.epoch를 읽고 변환하기 전에 날짜 체계를 확인하세요. 경계 날짜 및 시간대 문제는 별도로 처리됩니다.
| 당신의 상황 | 권장 사례 | 이유 |
|---|---|---|
| 내보낸 날짜는 전체적으로 약 1462일만큼 오프셋됩니다. | 통합 문서 날짜 체계를 확인하려면 먼저 workbook.epoch를 읽어보세요. | 1900과 1904 시스템의 차이는 1462일이며, 읽기 측의 잘못된 가정으로 인해 모든 일련 번호가 잘못 해석될 수 있습니다. |
| 셀이 숫자이지만 날짜로 표시할 수 없습니다. | number_format 날짜 형식 마스크를 확인하고 완료하세요. | 숫자 유형이 올바른 경우 형식이 누락되어 표시 이상이 발생할 수 있습니다. |
| 1900년 3월 또는 1900-02-29 이전 날짜가 데이터에 나타납니다. | 유효하지 않은 것으로 표시하거나 직접 검토로 전환하고 원래 일련번호를 유지합니다. | 이 날짜는 그레고리력에 존재하지 않으므로 강제로 변환해서는 안 됩니다. |
시간대가 포함된 datetime를 작성해야 합니다. | UTC로의 통합 변환 후 tzinfo 제거 | Excel은 시간대 저장을 지원하지 않으며 모든 시간은 인식하지 못하는 현지 시간입니다. |
| 플랫폼 간에 파일을 교환해야 합니다. | 날짜 체계를 명시적으로 선언 | 수신기의 기본 설정이 다르기 때문에 자동 오프셋이 생성될 수 있습니다. |
1900년과 1904년 날짜 체계의 차이점
XLSX 파일의 날짜는 기본적으로 부동 소수점 일련 번호이며 그 의미는 전적으로 통합 문서가 바인딩된 날짜 시스템에 따라 달라집니다. XLSX 사양에서는 두 가지 기본 시대를 허용합니다.
- 1900 날짜 시스템: Windows에서 기본적으로 사용되며 일련 번호 1은 1900-01-01을 나타냅니다.
- 1904 날짜 시스템: 초기 Mac에서 기본적으로 사용되며 일련 번호 0은 1904-01-01을 나타냅니다.
둘 사이에는 1462일이라는 고정 오프셋이 있는데, 이것이 '4년의 날짜 차이'의 주요 원인이다. 또한 1900 시스템에는 역사적인 문제가 있습니다. 1900을 윤년으로 잘못 처리하여 존재하지 않는 날짜인 1900-02-29가 Excel에서 합법화됩니다.
코어 비교
| 프로젝트 | 1900년 날짜 체계 | 1904년 날짜 체계 |
|---|---|---|
| 일련번호 시작점 | 일련번호 1은 1900-01-01에 해당합니다. | 일련번호 0은 1904-01-01에 해당합니다. |
| 일반적인 기본 소스 | Windows | 초기 맥 |
| 다른 시스템과의 오프셋 | 차이는 1,462일 | 차이는 1,462일 |
| 특별호 | 1900년을 윤년으로 잘못 계산한 것은 1900년 2월 29일에 존재합니다. | 이 글은 이러한 문제들을 다루지 않습니다 |
1900년 전의 데이터는 특별한 주의가 필요한 이유
1900년 3월 이전의 역사적 데이터를 다룬다면, 파이썬의 datetime 모듈은 2월 29일을 직접 표현할 수 없습니다. 공식 OpenPyxl 문서에 따르면, Excel 동작을 지원하기 위해 라이브러리는 1900 시스템에서 1월과 2월 날짜를 읽을 때 이 예외를 시뮬레이션하지만, 1900-02-29 자체는 이를 유효한 Python datetime 객체로 변환할 수 없습니다.
대부분의 최신 비즈니스 데이터의 핵심은 현재 워크북이 사용하는 시스템을 식별하고, 플랫폼 간 파일 교환 시 명시적으로 선언하여 수신자의 기본 설정이 달라져 발생하는 무음 오프셋을 방지하는 것입니다.
합성 예시: 경계 입력 및 처리 방법
문제를 설명하기 위해 합성 시나리오를 구성해 봅시다: 금융 시스템은 1904년 연도 시스템을 사용해 보고서를 내보내지만, 하위 ETL 스크립트는 기본적으로 1900년 시스템을 파싱합니다.
오류 또는 경계 입력 처리:
- 만약 일련번호 60을 입력하고 워크북이 1900 시스템이라면, 이는 엑셀의 가상 1900-02-29에 해당합니다. 네이티브 파이썬
datetime는ValueError를 던집니다. - 이 시점에서는 변환을 강요하지 말고, 대신 이상한 현상을 기록하여 원래 값이나 특별한 표지로 기록하세요. 왜냐하면 그 날짜는 그레고리력에 존재하지 않기 때문입니다.
- 시간대 정보가 포함된
datetime객체가 전달되어 작성되면, openpyxl은 자동으로 시간대를 변환하지 않고 먼저 tzinfo를 제거합니다; 그렇지 않으면 쓰기 오류나 오류가 발생할 수 있습니다. - 엑셀 자체는 시간대 저장을 지원하지 않으며, 모든 시간은 현지 시간으로 감지할 수 없습니다.
날짜 시스템 탐지 및 보안 변환 코드
다음 예시는 메모리 내 날짜 시스템 차이를 안전하게 처리하는 방법을 보여줍니다. 이 코드는 논리적 시연용일 뿐 실제로 파일을 읽거나 쓰지 않습니다. 자신의 잠긴 의존성 환경에서 실행되어야 합니다. Openpyxl >= 3.1.0을 권장합니다. 예시에는 네트워크 요청이나 파일 덮어쓰기 작업이 포함되지 않습니다; 모든 주장은 합성 데이터에 기반합니다.
from datetime import datetime
from io import BytesIO
from zipfile import ZipFile
from openpyxl import Workbook, load_workbook
from openpyxl.utils.datetime import from_excel, CALENDAR_MAC_1904, CALENDAR_WINDOWS_1900
assert from_excel(1, CALENDAR_MAC_1904) == datetime(1904, 1, 2)
assert from_excel(1, CALENDAR_WINDOWS_1900) == datetime(1900, 1, 1)
wb = Workbook()
wb.epoch = CALENDAR_MAC_1904
wb.iso_dates = True
value = datetime(2026, 9, 26, 12, 30)
wb.active["A1"] = value
assert wb.active["A1"].value == value
out = BytesIO()
wb.save(out)
with ZipFile(BytesIO(out.getvalue())) as z:
xml = z.read("xl/worksheets/sheet1.xml")
assert b't="d"' in xml and b"2026-09-26T12:30:00" in xml
restored = load_workbook(BytesIO(out.getvalue()))
assert restored.active["A1"].value == value
assert restored.epoch == CALENDAR_MAC_1904
수제 기준과 수동 검토 경계
| 현상을 관찰해 | 입력 조건 또는 경계 조건 | 예상 출력 또는 처리 결정 | 자동화가 적합한지 여부 |
|---|---|---|---|
| 모든 날짜는 1462일 간격으로 균일하게 조정되어 있습니다 | wb.epoch는 분석적 가정과 일치하지 않습니다 | wb.epoch를 읽은 후 일련번호를 다시 변환하세요 | 네 |
| 1900-02-29가 데이터에 나타났다 | 1900년형 일련번호 60의 시스템 | 원본 일련번호 60을 유지하되 유효하지 않은 날짜로 표시하세요 | 아니요, 사업의 의미는 수동으로 확인해야 합니다 |
| 시간이 부분적으로 손실되거나 어긋나 있습니다 | tzinfo와 함께 datetime를 입력하세요. | UTC로 균일하게 변환한 후, tzinfo는 제거되어 다시 작성됩니다 | 어떤 곳은 목표 시간대를 수동으로 정의해야 합니다 |
| 셀은 숫자를 표시하지만 날짜 형식입니다 | 값 유형은 맞지만 number_format가 빠져 있습니다 | 날짜 포맷 마스크를 확인하고 완성하세요 | 네 |
| 역사적 날짜(1900년 1월 1일 이전)는 이상한 점을 보여준다 | 1900년 1월 1일 이전 날짜 | 텍스트 저장 또는 전용 역사 데이터베이스로 전환하세요 | 아니요, XLSX는 이 상황에 적합하지 않습니다 |
코드 시연은 변환 논리의 정확성만을 검증하는 것일 뿐, 종단 간 효과를 나타내지 않는다는 점에 유의하세요. 실제 파일은 여러 날짜 형식, 조건부 형식, 또는 공식으로 생성된 날짜를 혼합할 수 있으며, 이들 모두 추가적인 파싱 계층이 필요합니다. 1900년 3월 이전의 날짜, 교차 시역 협력 데이터, 또는 음력 또는 회계연도 같은 비표준 달력에 접근할 때는 수동 검토 과정을 사용해야 하며, 자동화된 스크립트는 임의로 수정해서는 안 됩니다.
🎯 어떤 방법이 당신에게 맞나요?
내보내기 파일에서 날짜를 읽어야 한다면
먼저 workbook.epoch를 읽고, 날짜 시스템을 확인한 뒤, 일련번호를 다시 변환할지 결정하세요.
만약 당신의 데이터가 1900년 3월 이전의 날짜를 포함한다면
1900-02-29와 관련된 기록을 무효로 표시하고, 원본 일련번호를 유지한 뒤, 매뉴얼에 제출하여 사업 의미를 확인하세요.
엑셀에 시간대를 적어야 한다면
먼저 UTC로 균일하게 변환한 다음, tzinfo를 제거하세요; 목표 시간대는 수동으로 정의해야 합니다.
다른 시스템과 파일을 교환하고 싶다면요
날짜 시스템을 명시적으로 선언하고, 수신 측에서 읽을 날짜 값을 검증합니다.
❓ 자주 묻는 질문 (FAQ)
1. 왜 전체 수출 날짜가 약 4년 정도 차질로 조정되어 있나요?
흔한 이유는 워크북의 날짜 시스템이 독서 측의 가정과 맞지 않는다는 점입니다. 1900년과 1904년 시스템 사이에는 1,462일의 간격이 있습니다.
2. iso_dates: datetime을 자동으로 문자열로 변환하나요?
아니. iso_dates는 파일 내 날짜 직렬화 방법만 제어하며, 메모리에서 datetime를 자동으로 문자열로 변환하지는 않습니다.
3. 왜 1900-02-29를 Python 날짜로 변환할 수 없는 걸까요?
1900년 시스템은 1900년을 윤년으로 잘못 간주하여 1900-02-29가 엑셀에는 존재하지만 그레고리력에는 존재하지 않는 경우가 발생합니다. 파이썬의 datetime는 ValueError를 던져서 원래 값이나 특수 태그를 기록해야 합니다.
4. 엑셀에서 시간대를 표시한 날짜 시간을 어떻게 써야 할까요?
엑셀은 시간대 저장을 지원하지 않습니다. 먼저, 일관되게 UTC로 변환한 뒤, tzinfo를 제거한 후에 작성해야 합니다; OpenPyXL은 자동으로 시간대를 변환하지 않습니다.
📝 요약
날짜 오프셋 문제는 보통 워크북의 날짜 시스템에서 발생합니다. 변환 전에 workbook.epoch를 확인하면 대부분의 무음 오류를 피할 수 있습니다. 경계 날짜와 시간대 문제는 수동 검토에 맡겨야 합니다.
참고문헌 및 다음 단계
- 공식 OpenPyxl 날짜 및 시간 문서: https://openpyxl.readthedocs.io/en/stable/datetime.html
- 마이크로소프트의 1900/1904 연도 시스템 설명: https://docs.microsoft.com/en-us/office/troubleshoot/excel/1900-and-1904-date-system
- 1900년 윤년 버그에 대한 마이크로소프트 설명: https://docs.microsoft.com/en-us/office/troubleshoot/excel/wrongly-assumes-1900-is-leap-year
다음: 접근 가능한 불안한 엑셀 샘플을 선택하고, 위의 에포크 탐지 코드를 실행하여 날짜 시스템이 처리 논리와 일치하는지 확인하세요. 불일치가 발견되면 변환 파라미터를 조정하여 번역된 산출물을 생성하세요.
문서 번역을 위해 이 체크리스트를 사용하세요
먼저, 어떤 내용이 텍스트인지, 어떤 내용이 공식인지 비즈니스 코드인지 결정한 다음, 표를 번역하세요. 번역 후 검사는 중국어가 목표 언어로 변환되었는지 확인할 뿐만 아니라, 공식, 식별자, 인용 관계가 변경되지 않았는지도 확인합니다.
OmniDoc (제품 입력)는 다중 형식의 문서 번역 포털을 제공하며, 공식 웹사이트에서는 OCR, 용어집, 이중 언어 참고 기능을 소개합니다. 파일을 직접 시작하고자 하는 팀에게는 실제 샘플을 활용해 평가할 가치가 있는 경로입니다. 업로드를 승인한 익명 파일을 사용해 이 기사의 체크리스트와 결과를 확인해 주시기 바랍니다. 이 글은 OmniDoc이 기사에서 언급한 오픈 소스 라이브러리나 내부 알고리즘을 사용한다고 주장하지 않으며, 제품 성능 테스트를 예시로 대체하지도 않습니다.


