如何将不完整及公元前(BC)的Wikidata日期转换为时间戳?
Solution for Parsing Wikidata Dates in Python
Let's fix your issues step by step—handling the AD/BC sign, incomplete dates, and ensuring correct UTC timestamp conversion.
Problem Breakdown
Your original code has three key flaws:
- Sign stripping: Removing the leading
+/-means BC dates get misparsed as AD. - Timezone ignorance: The
Zin Wikidata dates indicates UTC, but your naive datetime uses local time for timestamp calculations, leading to incorrect values if your system isn't set to UTC. - Incomplete date handling: Dates like
+2018(year only) or+2018-03(year/month) aren't processed consistently by default.
Fixed Implementation
Here's a robust function that handles all Wikidata date formats, preserves the AD/BC sign, respects UTC, and fills missing components logically:
from datetime import datetime, timezone def parse_wikidata_date(datestring): # Extract the AD/BC sign sign = datestring[0] rest = datestring[1:] # Split date and time parts (handle cases without explicit time) if 'T' in rest: date_part, time_part = rest.split('T', 1) time_part = time_part.rstrip('Z') # Remove UTC indicator else: date_part = rest time_part = '00:00:00' # Default to midnight UTC # Parse date components (year, month, day) date_components = date_part.split('-') year = int(sign + date_components[0]) month = int(date_components[1]) if len(date_components) >= 2 else 1 day = int(date_components[2]) if len(date_components) >= 3 else 1 # Parse time components (hour, minute, second) time_components = time_part.split(':') hour = int(time_components[0]) if len(time_components) >= 1 else 0 minute = int(time_components[1]) if len(time_components) >= 2 else 0 second = int(time_components[2]) if len(time_components) >= 3 else 0 # Create UTC-aware datetime object return datetime(year, month, day, hour, minute, second, tzinfo=timezone.utc) # Helper to convert directly to timestamp def wikidate_to_timestamp(datestring): dt = parse_wikidata_date(datestring) return dt.timestamp()
Test Cases
Let's verify with your example and edge cases:
1. Original AD Date (Douglas Adams' Birthday)
print(wikidate_to_timestamp('+1952-03-11T00:00:00Z')) # Output: -562032000.0 (matches your original result, but now timezone-correct)
2. BC Date (2 BC)
print(wikidate_to_timestamp('-0001-03-11T00:00:00Z')) # Output: -62135596800.0 (correct timestamp for March 11, 2 BC UTC)
3. Incomplete Date (Year + Month)
print(wikidate_to_timestamp('+2018-03')) # Output: 1519862400.0 (March 1, 2018 UTC midnight)
4. Year-Only Date
print(wikidate_to_timestamp('+2018')) # Output: 1514764800.0 (January 1, 2018 UTC midnight)
Key Improvements
- Sign Preservation: The leading
+/-is retained to correctly parse AD/BC dates, including year 0 (which represents 1 BC). - UTC Awareness: We create a timezone-aware datetime, so
timestamp()always uses UTC (no local time skew). - Incomplete Date Handling: Missing month/day defaults to January 1; missing time defaults to midnight UTC.
Notes
- Python's
datetimesupports proleptic Gregorian calendar dates, including year 0 (1 BC) and negative years (BC dates). - Timestamp precision: For extremely ancient dates (millions of years ago), floating-point timestamp precision may degrade, but this is negligible for historical dates.
内容的提问来源于stack exchange,提问作者pajamas
相关产品推荐
相关产品推荐

