Как конвертировать python datetime.datetime, чтобы увеличить серийный номер даты

Мне нужно преобразовать даты в серийные номера Excel для сбора данных script Я пишу. Играя с датами в моей книге OpenOffice Calc, я смог вывести, что "1-янв. 1899 00:00:00" отображает нулевое число.

Я написал следующую функцию для преобразования из объекта datetime python в серийный номер Excel:

def excel_date(date1):
    temp=dt.datetime.strptime('18990101', '%Y%m%d')
    delta=date1-temp
    total_seconds = delta.days * 86400 + delta.seconds
    return total_seconds

Однако, когда я пробую несколько примерных дат, цифры отличаются от тех, которые я получаю, когда я форматирую дату как число в Excel (хорошо OpenOffice Calc). Например, тестирование "2009-03-20" дает 3478032000 в Python, в то время как Excel выделяет серийный номер 39892.

Что не так с формулой выше?

* Примечание. Я использую Python 2.6.3, поэтому не имею доступа к datetime.total_seconds()

Ответ 1

Похоже, что формат "серийной даты" Excel на самом деле является числом дней с 1900-01-00, причем дробная составляющая составляет дробную часть на основе http://www.cpearson.com/excel/datetime.htm. (Думаю, что эту дату следует считать 1899-12-31, так как нет такой вещи, как 0-й день месяца)

Итак, похоже, что это должно быть:

def excel_date(date1):
    temp = dt.datetime(1899, 12, 30)    # Note, not 31st Dec but 30th!
    delta = date1 - temp
    return float(delta.days) + (float(delta.seconds) / 86400)

Ответ 2

Хотя это не совсем важно для формата даты Excel, это был лучший хит для экспорта даты Python в Excel. То, что я нашел особенно полезным и простым, - это просто экспорт с использованием strftime.

import datetime
current_datetime = datetime.datetime.now()
current_datetime.strftime('%x %X')

Это будет выводиться в следующем формате '06/25/14 09:59:29 ', который принимается Excel как действительная дата/время и позволяет сортировать в Excel.

Ответ 3

Если проблема заключается в том, что мы хотим, чтобы DATEVALUE() превосходил серийный номер для дат, можно использовать функцию toordinal(). Серийные номера Python начинаются с 1 января года 1, тогда как excel начинается с 1 января 1900 года, поэтому примените смещение. Также см. Excel 1900 високосный год (https://support.microsoft.com/en-us/help/214326/excel-incorrectly-assumes-that-the-year-1900-is-a-leap-year)

def convert_date_to_excel_ordinal(day, month, year) :

    offset = 693594
    current = date(year,month,day)
    n = current.toordinal()
    return (n - offset)

Ответ 4

С помощью стороннего модуля xlrd.xldate вы можете предоставить кортеж, структурированный как (year, month, day, hour, minute, second) и, при необходимости, рассчитать долю дня из любого компонента микросекунд:

from datetime import datetime
from xlrd import xldate
from operator import attrgetter

def excel_date(input_date):
    components = ('year', 'month', 'day', 'hour', 'minute', 'second')
    frac = input_date.microsecond / (86400 * 10**6)  # divide by microseconds in one day
    return xldate.xldate_from_datetime_tuple(attrgetter(*components)(input_date), 0) + frac

res = excel_date(datetime(1900, 3, 1, 12, 0, 0, 5*10**5))
# 61.50000578703704