【问题标题】:Issues with FSCalendar and current timezoneFSCalendar 和当前时区的问题
【发布时间】:2021-06-21 15:44:36
【问题描述】:

我正在使用 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

我知道如何解决选择日期标签的问题,我只需要将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
}

【问题讨论】:

  • 您的日期比较实际上是如何实现的?您需要使用 Calendar based 与日历实例上设置的正确时区进行比较
  • @Paulw11 在我发布的示例代码中你可以看到它。获取一天的所有事件:date.compare(.isSameDay(rowDate)) 并获取一天的开始:.dateAt(.startOfDay)。拜托,你能在答案中告诉我如何用一些样本正确地做到这一点吗?我不知道如何解决它。
  • 我不认识这个语法date.compare(.isSameDay(rowDate))dateAt(.startOfDay) 也一样——这是日期的扩展吗?你能显示那个代码吗?
  • @Paulw11 .dateAt(.startOfDay) 和 .compare(.isSameDay(rowDate)) 来自 SwiftDate pod,不知道这个项目为什么要使用它,这是一个由其他人发起的非常大的项目。看来 SwiftDate 是 Date 的升级版。
  • 您应该始终提及您正在使用的任何相关 pod。在这种情况下,这是您的问题。您需要为您的日期设置region,否则日期计算不正确。

标签: ios swift timezone fscalendar


【解决方案1】:

好吧,在将数据库的所有日期转换为 localDate() 之后,然后将它们添加到 FSCalendar 之后,终于解决了这个问题,并且在使用 FSCalendar 代表/侦听器返回的每个日期之前转换为 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
    }
}

【讨论】:

  • 虽然这可以解决问题,但它并不是最好的解决方案。您需要涉及Calendar 实例才能正确执行此操作。请参阅我对您关于在 swift date pod 中使用区域的问题的评论。就个人而言,这个 POD 似乎比它的价值更麻烦。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-08
  • 2016-09-11
  • 2011-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-07
相关资源
最近更新 更多