JTAppleCalendar: Wrong selected date

Version: 6.0

screen shot 2017-01-02 at 14 04 27

Selected Date: (Date) $R0 = 2017-01-09 22:00:00 UTC

    func calendar(_ calendar: JTAppleCalendarView, didSelectDate date: Date, cell: JTAppleDayCellView?, cellState: CellState) {
        handleCellTextColor(view: cell, cellState: cellState)
        handleCellSelection(view: cell, cellState: cellState, date: date, isSelectionEvent: true)
    }

Here is my configuration and the problem occurs even if I don’t set a timezone.

 func configureCalendar(_ calendar: JTAppleCalendarView) -> ConfigurationParameters {
        var calendar = Calendar.current
        calendar.timeZone = TimeZone(secondsFromGMT: NSTimeZone.local.secondsFromGMT())!
        return ConfigurationParameters(startDate: startDate!, endDate: endDate!, numberOfRows: 6, calendar: calendar, generateInDates: .forAllMonths, generateOutDates: .tillEndOfGrid, firstDayOfWeek: .monday)
 }

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 19 (8 by maintainers)

Most upvoted comments

Yes you have a point. For me it is important to work with the “local date”. So for me this is resolved likes this:

  • The user clicks on the 04.01.2016
  • The date prints 03.01.2016 23:00 which is the correct date in UTC, since i am living in GMT+1
  • In order to further work with the date object representing 03.01.2016 23:00 in GMT+1 i am using the following conversion:
    //date is the object coming from the didSelectDate delegate method
    let dateInRegion = date.inLocalRegion()
    let seconds = dateInRegion.region.timeZone.secondsFromGMT(for: date)
    let localDate = Date(timeInterval: TimeInterval(seconds), since: date)

If i now print localDate I get 2017-01-04 00:00:00 +0000 which is the correct date for me as my app proceeds. The above code snippet makes use of the superb SwiftDate library by the way which makes working with dates a lot easier and more convenient. I am not a contributor or anything for the library I just thought I would mention it if people would try to go with my solution and wonder why it does not work for them.

@dehlen I see the issue. I do not believe there is an error. Here are my results.

I made my time zone information to be the same as yours:

▿ gregorian (fixed)
  - identifier : Foundation.Calendar.Identifier.gregorian
  - kind : "fixed"
  ▿ locale : Optional<Locale>
    ▿ some : en (fixed)
      - identifier : "en"
      - kind : "fixed"
  ▿ timeZone : Europe/Berlin (fixed)
    - identifier : "Europe/Berlin"
    - kind : "fixed"
    ▿ abbreviation : Optional<String>
      - some : "GMT+1"
    - secondsFromGMT : 3600
    - isDaylightSavingTime : false
  - firstWeekday : 1
  - minimumDaysInFirstWeek : 1

And i had this code:

func calendar(_ calendar: JTAppleCalendarView, didSelectDate date: Date, cell: JTAppleDayCellView?, cellState: CellState) {
     handleCellSelection(view: cell, cellState: cellState)
     handleCellTextColor(view: cell, cellState: cellState)
     print(date)
     print(formatter.string(from: date))
}

And the results after selecting the 10th were: screen shot 2017-01-04 at 9 38 10 am

2017-01-09 23:00:00 +0000 // The result of date
2017 01 10                // The result of formatted date

It is important to understand that when you do a print(date) what is happening here is that the print command tries to format that date with its own formatting. This formatting may be different than your timeZone and locale.

In order to print the correct date on console, you need a formatter that is configured with the same timeZone and locale information of your Calendar() instance.

you can do this by:

let formatter = DateFormatter()
formatter.timeZone = Calendar.current.timeZone
formatter.locale = Calendar.current.locale
print(formatter.string(from: date))

This will give you the same date formatted to your time zone rather than what ever default time zone contained in the print command.

Lesson to be learned: printing dates directly on console using the print command can be very deceptive.

I hope this solves your issue?

This may be a dumb/blunt solution but maybe it takes out some of the hassle:

Could those errors be resolved by simply setting the time in the selectedDate property to 12:00 UTC instead of 00:00 UTC ?

Then the selected day should be the same across the globe and since we’re dealing with calendar dates, the timestamp shouldn’t be relevant.

Or am I thinking the wrong way?

@onurays but thats the thing. The date is correct. You can do operations on dates and it should work properly. Its only when you use a print command, you have to format it so that it displays correctly on the console.

For instance, put this in your PlayGround:

import UIKit


// ____________________________________________________________________________
// First I create a calendar to match your Calendar.current in Berlin
var myCalendar1 = Calendar(identifier: .gregorian)
myCalendar1.timeZone = TimeZone(identifier: "Europe/Berlin")!
myCalendar1.locale = Locale(identifier: "en")

// Next I create my date formatter
let aFormatter1 = DateFormatter()
aFormatter1.dateFormat = "yyyy MM dd"
aFormatter1.timeZone = myCalendar1.timeZone
aFormatter1.locale = myCalendar1.locale



// Even though theFifth is the 5th, Myplayground is showing it as the 4th. (on the right)
// But date actually IS the fifth. You can operate on it without converting it to strings
let theFifth1 = aFormatter1.date(from: "2017 01 05")

// ____________________________________________________________________________

// This second calendar in my own time zone
var myCalendar2 = Calendar(identifier: .gregorian)
myCalendar2.timeZone = TimeZone(identifier: "America/Vancouver")!
myCalendar2.locale = Locale(identifier: "en_US")

// This is a second formatter in my own time zone
let aFormatter2 = DateFormatter()
aFormatter2.dateFormat = "yyyy MM dd"
aFormatter2.timeZone = myCalendar2.timeZone
aFormatter2.locale = myCalendar2.locale

let theFifth2 = aFormatter2.date(from: "2017 01 05")

Your results should look like this: screen shot 2017-01-04 at 11 07 57 am

Although they are the same date, they are displayed differently on console. But you do not have to change the dates into string to work with them. You can use them directly.

Your calendar might look perfect with FSCalendar in your timeZone right now, but are you sure it will still be displayed the same way in other regions around the world?

Here are some issues on FSCalendar that has the same problems you are experiencing:

  1. 531
  2. 459
  3. 246 etc etc etc

In all responses, the answer is the same. Format your date using the correct formatter. When ever we work with dates, we should always take regions into consideration. Therefore, whether you use FSCalendar, or this library, make sure you format correctly. Cheers 🍻

@patchthecode Unfortunately, I had to switch to the FSCalendar (because of the time pressure). I will try to test it again at weekend.

I know, DateFormatter formats correctly. But po or print(date) doesn’t. So we have problems if we need operations on Dates, not Strings.

By the way, you already had your star for this beautiful library 😃