Конвертировать Double (количество дней с De c 30, 1899) в Date в Swift? - PullRequest
1 голос
/ 01 февраля 2020

У меня есть двойное значение, которое представляет количество дней с 30 декабря 1899 года (обычное значение TDateTime в Delphi). Например: 43854.4410269444

Возможно ли создать действительное значение Date из этого двойного числа?

Ответы [ 2 ]

2 голосов
/ 01 февраля 2020

Один из способов - получить Date, представляющий «1899-12-30», затем вызвать addingTimeInterval.

// either parse a date string...
let formatter = DateFormatter()
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd"

let epoch = formatter.date(from: "1899-12-30")!
// or calculate the time directly from 1970
//let epoch = Date(timeIntervalSince1970: -86400 * 25569)

// now we add the quality of the number of days times the number of seconds in a day
let numberOfDays = 43854.4410269444
let result = epoch.addingTimeInterval(86400 * numberOfDays)

enter image description here

1 голос
/ 01 февраля 2020

Вот моя попытка решить проблему (см. Ниже, как я вычислил магическое число c):

extension Date {
    init(fromDelphiTDateTime delphiDate: Double) {
        //Number of seconds between 12/30/1899 12:00 AM and 1/1/1970 12:00 AM
        let tDateTimeUnixTimeOffset = 2209161600.0 

        //24 * 60 * 60
        let numberOfSecondsInDay = 86400.0 

        let delphiTDateTimeAsUnixTime = delphiDate * numberOfSecondsInDay - tDateTimeUnixTimeOffset
        self.init(timeIntervalSince1970: delphiTDateTimeAsUnixTime)
    }
}

Я предположил, что TDateTime не имеет никакой информации о часовом поясе. Поскольку Unix time (timeIntervalSince1970) указано в UT C, вам необходимо преобразовать значение TDateTime в UT C, если оно находится в другом часовом поясе.

Примеры:

//Dec 30, 1899 at 12:00 AM
let date1 = Date(fromDelphiTDateTime: 0)

//Jan 24, 2020 at 11:04 AM
let date2 = Date(fromDelphiTDateTime: 43854.4410269444)

И вот как я вычислил волшебный номер c 2209161600.0, используя Swift:

let zeroTDateTimeComponents = DateComponents(calendar: Calendar.init(identifier: .gregorian), timeZone: TimeZone(secondsFromGMT: 0), year: 1899, month: 12, day: 30, hour: 0, minute: 0, second: 0)
let zeroTDateTime = zeroTDateTimeComponents.date
let tDateTimeUnixTimeOffset = zeroTDateTime?.timeIntervalSince1970 //the value is 2209161600.0

Надеюсь, это поможет, и я был бы признателен, если сообщество подтвердит или улучшит мой ответ. Некоторые модульные тесты с существующими известными парами TDateTime и его двойным значением наверняка помогут.

...