Thanks for creating this library. What is your intended way for code that uses FSCalendar to deal with time zones? Since we can set an FSCalendar's identifier and locale, I'd have thought that we could set its time zone as well, but I'm not seeing a way to do that. It looks like the time zone was always GMT+0 in version 1.7 and is always the local time zone in version 1.7.1.
EDIT: For some context--I may not always want the calendar's timezone to be the local time zone.
I don't think it's necessary anymore. See #195
it is necessary, you may never guess the client needs
look what I had to to for supporting different time zone when I needs
@interface MWFSCalendar : FSCalendar
@end
@implementation MWFSCalendar
- (instancetype) initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]){
[self setValue:[NSTimeZone timeZoneWithName:@"UTC"] forKey:@"timeZone"];
[self performSelector:NSSelectorFromString(@"invalidateDateTools")];
}
return self;
}
@end
If you do not want to use the undocumented features of FSCalendar, then there is another solution.
FSCalendar uses the private "timezone" field to initialize the Gregorian calendar, which is then used to determine the current day, the first day of the month, initialize sticky headers, add days to dates, etc. But most importantly, in the FSCalendarDelegate, FSCalendarDelegateAppearance, andFSCalendarDataSourcecallbacks, thedateobjects point to the beginning of the day, taking into account thetimezone` field of the calendar. You can convert a date like this to a date given your desired time zone:
class MyDataSource: FSCalendarDataSource {
func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int {
let dateInDesiredTimeZone = date.dateOnly(self.calendar, oldCalendar: Calendar.current)
// ...
}
}
Here is a handy extension for converting dates to the beginning of the day with between time zones:
private extension Date {
func dateOnly(_ newCalendar: Calendar, oldCalendar: Calendarl) -> Date {
let yearComponent = oldCalendar.component(.year, from: self)
let monthComponent = oldCalendar.component(.month, from: self)
let dayComponent = oldCalendar.component(.day, from: self)
let newComponents = DateComponents(timeZone: newCalendar.timeZone,
year: yearComponent,
month: monthComponent,
day: dayComponent)
let returnValue = newCalendar.date(from: newComponents)
return returnValue!
}
}
Just don't forget to change your timezone in FSCalendar#dateFormatter. Fortunately, this is a public field:
func setupCalendarView() {
// ...
calendarView.formatter.calendar = calendar
calendarView.formatter.timeZone = calendar.timeZone
}
Both mine and the previous method work on the latest version at the moment (2.8.2). Because one of the goals of FSCalendar is to ignore the timezone (#195), it is unlikely that my solution will ever stop working.
Most helpful comment
look what I had to to for supporting different time zone when I needs