patchthecode / JTAppleCalendar

The Unofficial Apple iOS Swift Calendar View. Swift calendar Library. iOS calendar Control. 100% Customizable
https://patchthecode.com
MIT License
7.57k stars 808 forks source link

cellState.text doesn't use the specified calendar? #176

Closed dbmrq closed 7 years ago

dbmrq commented 7 years ago

I'm having the same problem as in #147, but I don't think I should need to use a different Calendar.

Here's an example:

class ViewController: UIViewController, JTAppleCalendarViewDelegate, JTAppleCalendarViewDataSource {

    @IBOutlet weak var calendarView: JTAppleCalendarView!

    override func viewDidLoad() {
        super.viewDidLoad()
        calendarView.dataSource = self
        calendarView.delegate = self
        calendarView.registerCellViewXib(file: "CellView")
    }

    func configureCalendar(_ calendar: JTAppleCalendarView) -> ConfigurationParameters {
        let calendar = Calendar.current
        let startDate = calendar.date(byAdding: .month, value: -3, to: Date())!
        let endDate = calendar.date(byAdding: .month, value: 3, to: Date())!

        return ConfigurationParameters(
            startDate: startDate,
            endDate: endDate,
            numberOfRows: 6,
            calendar: calendar.identifier,
            generateInDates: .forAllMonths,
            generateOutDates: .tillEndOfRow,
            firstDayOfWeek: .sunday
        )
    }

    func calendar(_ calendar: JTAppleCalendarView,
                  willDisplayCell cell: JTAppleDayCellView, date: Date, cellState: CellState) {
        print(Calendar.current.component(.day, from: date), cellState.text)
    }

}

In the configureCalendar function I specify Calendar.current as the calendar that should be used. Then in willDisplayCell I use Calendar.current again to print the day, and I print cellState.text too. But I get different results:

25 26
26 27
27 28
28 29
29 30
30 1
1 2
2 3
3 4
…

So what Calendar is cellState.text using? Shouldn't it be the one I specified in configureCalendar?

patchthecode commented 7 years ago

Ok can you do one thing? (assuming you are using master branch)

    func calendar(_ calendar: JTAppleCalendarView,
                  willDisplayCell cell: JTAppleDayCellView, date: Date, cellState: CellState) {
        print(date, cellState.text)
    }

are they both the same date?

patchthecode commented 7 years ago

If they are both the same date, then configure your calendar as this:

var calendar = Calendar.current
calendar.timeZone = TimeZone(secondsFromGMT: 0)!

Then provide it to your configure method

What you specified in configure calendar was not a calendar You gave it an identifier.

Calendar identifiers are of type .gregorian or .persian etc etc etc Once you supply the type of calendar you want to use, I then generate one internally. The generated internal calendar is this set calendar.timeZone = TimeZone(secondsFromGMT: 0)!

I did this because different users from different time zones were getting either an off-by-one-day error. So to solve this, i set all calendars to start from 0 from GMT. If you are formatting dates to display using a calendar instance, then your calendar() instance should also start from gmt 0.

I am still debating whether or not i should let the user supply the actual configured calendar() instance instead of the identifier. Because either way, you will still have to set the calendar to

calendar.timeZone = TimeZone(secondsFromGMT: 0)!

which was something i was trying to not make the user have to do.

Of course, this explanation is assuming I have understood your problem correctly?

dbmrq commented 7 years ago

Thanks for the answer!

Providing it to the configure method doesn't make a difference, but changing the timeZone of the Calendar I use to call component(.day, from: date) does, like so:

func calendar(_ calendar: JTAppleCalendarView,
              willDisplayCell cell: JTAppleDayCellView, date: Date, cellState: CellState) {
    var calendar = Calendar.current
    calendar.timeZone = TimeZone(secondsFromGMT: 0) ?? calendar.timeZone
    print(calendar.component(.day, from: date), cellState.text)
}

So I think the problem is cellState.text always uses the same time zone… now I realized I don't even set the calendar itself in configureCalendar, just the identifier. So I can work around that by always setting the timezone like that before doing any calculations, but that seems very messy and error prone. Shouldn't cellState.text use whatever calendar I want with its own time zone and all?

Also many people (me included) use Date extensions, like this one, which has a day property:

public var day: Int { return Date.sharedCalendar.component(.day, from: self) }

And sharedCalendar there is Calendar.autoupdatingCurrent. It's really convenient, you can just do date.day and get the day.

But now I can't use that, because it gets the current time zone as well (like it should), and JTAppleCalendar doesn't. So every time I work with JTAppleCalendar I'll have to set a new calendar and specify the time zone and all that, it's pretty annoying.

I could try and help change this if you want, but I'm not sure if there's more to it than I'm seeing. Is there a reason why you made it this way?

patchthecode commented 7 years ago

hmm... this is too long to talk out. haha. I will do so in a bit. But if youre available now, we can text chat here https://gitter.im/patchthecode/JTAppleCalendar

because texting here is very slow

patchthecode commented 7 years ago

I need to debug with someone who is experiencing the wrong text. From my end, and many others, the dates are correct. But the issue seems to be with time zones. So if youre available to debug, then let me know.

dbmrq commented 7 years ago

Hey, I'm sorry, I was busy before. But sure, I can help you debug. :)

patchthecode commented 7 years ago

OK. in 15 mins? wil be here https://gitter.im/patchthecode/JTAppleCalendar

dbmrq commented 7 years ago

I'm there.

patchthecode commented 7 years ago

So, can I close this issue now?

dbmrq commented 7 years ago

Yes, thanks :)

patchthecode commented 7 years ago

cool.