FSCalendar 和当前时区的问题

Issues with FSCalendar and current timezone

我正在使用 FSCalendar 显示日期事件。我在西班牙(GMT+1 时区),我想展示 5 个将在西班牙发生的事件,所以我将首先在 GMT+1 时区向您展示它们:

march 1, 00:00 - day 1a
march 1, 11:16 - day 1b
march 1, 19:48 - day 1c
march 2, 00:00 - day 2a
march 3, 00:00 - day 3a

这些事件以 UTC 格式存储在数据库中,因此它们以 GMT+0 存储,因此所有事件都少了一小时。它们存储为:

february 28, 23:00 - day 1a
march 1, 10:16 - day 1b
march 1, 18:48 - day 1c
march 1, 23:00 - day 2a
march 2, 23:00 - day 3a

好的,现在,我需要在显示 FSCalendar 时,日期必须不是 UTC 显示,而是设备时区 GMT+1,所以日期必须是我写的第一个,而不是第二。但是当我打开 FScalendar 时,一切都是错误的。

如果我在 3 月 1 日单击 ,则所选日期标签打印 2 月 28 日,事件列表打印如下:

february 28, 23:00 - day 1a

如果我点击 3 月 2 日,选择的日期标签打印 3 月 1 日,事件列表打印如下:

march 1, 10:16 - day 1b
march 1, 10:48 - day 1c
march 1, 23:00 - day 2a

如果我在 3 月 3 日单击 ,所选日期标签将打印 3 月 2 日,事件列表将打印如下:

march 2, 23:00 - day 3a

我知道如何解决selected date label的问题,我只需要将calendarView.selectedDate转换成本地时区然后在标签中显示它,但我不知道如何解决其他问题日期显示在错误的日期并且使用 UTC 时区而不是本地 GMT+1 时区。我搜索了如何处理时区和 FSCalendar,据说它是自动的,我不需要做任何事情。所以我不知道如何解决这个问题。这些是我的代码的重要部分:

设置日历

calendarView = FSCalendar()
calendarView.dataSource = self
calendarView.delegate = self
calendarView.select(Date())

检查日历的哪些日期有事件,以便用 FSCalendar 上的事件标记它们

for index in 0..<collection.count {
    if let date = collection.date(field: dateField)?.dateAt(.startOfDay), datesWithEvents[date] == nil {
        datesWithEvents[date] = events(for: date)
    }
}

获取某个日期的所有事件

private func events(for date: Date) -> [Int] {
    var events: [Int] = []
    for index in 0..<collection.count {
        if let rowDate = collection.date(field: dateField), date.compare(.isSameDay(rowDate)) {
            events.append(index)
        }
    }
    return events
}

从我的数据库中获取日期(集合)

func date(field: String) -> Date? {
    if let item = currentRow, fieldTypes[field] == .date {
        if let timeInterval = item[columnIndex] as? Int64 {
            return Date(timeIntervalSince1970: Double(timeInterval))
        }
    }
    return nil
}

好吧,在将数据库的所有日期转换为 localDate() 之后将它们添加到 FSCalendar 之后,终于解决了它,并且在使用之前将 FSCalendar delegates/listeners 返回的每个日期转换为 localDate()他们显示每一天的事件等...然后,事件被正确地放置在他们的日子里。

我使用此扩展程序将日期转换为本地时区日期:

public extension Date {
    func localDate() -> Date {
        let timeZoneOffset = Double(TimeZone.current.secondsFromGMT(for: self))
        guard let localDate = Calendar.current.date(byAdding: .second, value: Int(timeZoneOffset), to: self) else {return Date()}

        return localDate
    }
}