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