Reputation: 6358
I'm struggling to understand why when I read from append dates .day
and .weekday
are not matching expected ones.
In one function dates()
I get actual date, get first day of the month, get a days range for month, and in a loop I append all the dates for that month to datesArray
. at print the array is correct, starts at date 1 and ends at date 28 ( current month ).
Then in cellForRowAt
in CalendarTableViewController
I assign the date to the row. Get components from the date. Then I compose cellLabel.text
with the components.day
+ dayNamesArray[components.weekday]
.
Results are wrong: the cells are off by one day starting at day 2(instead of 1) and ending at day 1(instead of 28), as day name is wrong.
Where to check for what's offsetting the results?
Many thanks as usual.
Here are the two functions:
func dates() {
datesArray.removeAll()
// Set calendar and date
let calendar = Calendar.current
let date = Date()
// Get range of days in month
let range = calendar.range(of: .day, in: .month, for: date)! // Range(1..<32)
// Get first day of month
var firstDayComponents = calendar.dateComponents([.year, .month, .day, .weekday], from: date)
self.displayedMonth = firstDayComponents.month!
self.monthCounter = self.displayedMonth - 1
firstDayComponents.day = range.lowerBound
let firstDay = calendar.date(from: firstDayComponents)!
var dayToAppend: Date = calendar.date(byAdding: DateComponents(day: 1), to: firstDay)!
for date in 1...range.count {
datesArray.append(dayToAppend)
dayToAppend = calendar.date(byAdding: DateComponents(day: 1), to: dayToAppend)!
}
self.actualMonthLabel.text = self.monthsArray[self.monthCounter]
print("dateArray is: \(datesArray)") // array is correct
}
and in TableView :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "calendarCell", for: indexPath) as!CalendarTableViewCell
// Configure the cell...
let date = datesArray[indexPath.row]
print(date)
let calendar = Calendar.current
let components = calendar.dateComponents([.year, .month, .day, .weekday], from: date)
print("month is: \(String(describing: components.month))") // correct
print("day is: \(String(describing: components.day))") // +1
print("weekdayIs: \(String(describing: components.weekday))") // +1
cell.dayLabel.text = "\(String(describing: components.day!))" + " " + "\(dayNamesArray[components.weekday! - 1])"
if indexPath.row == self.actualDay - 1 && self.actualMonth == self.displayedMonth {
cell.dayLabel.backgroundColor = UIColor.red.withAlphaComponent(0.3)
}
return cell
}
Upvotes: 0
Views: 275
Reputation: 342
Try to set calendar timezone as UTC and try same. Hope it will work for you.
Upvotes: 0
Reputation: 2435
Look closely at the marked lines your code:
let firstDay = calendar.date(from: firstDayComponents)!
var dayToAppend: Date = calendar.date(byAdding: DateComponents(day: 1), to: firstDay)! // <<--!!!
for date in 1...range.count {
datesArray.append(dayToAppend) // <--!!!
dayToAppend = calendar.date(byAdding: DateComponents(day: 1), to: dayToAppend)!
}
You first get the firstDay
of the month. Then you add 1 day (so dayToAppend
is the 2nd of the month) and THEN you add dayToAppend
to your array. So your array starts with the second day of the month. Not with the first.
So the solution would be:
let firstDay = calendar.date(from: firstDayComponents)!
var dayToAppend: Date = firstDay // <-- only line changed
for date in 1...range.count {
datesArray.append(dayToAppend)
dayToAppend = calendar.date(byAdding: DateComponents(day: 1), to: dayToAppend)!
}
The reason why you thought that everyting was good: you probably didn't take into account time zones. For example when I print out the date object for 1st February it looks like this: 2019-01-31 23:00:00 +0000
. I live in GMT+1. The Date object says 23:00 GMT. This means it's 24:00 / 00:00 GMT+1. Which is the next day.
Always read printed Date objects carefully. :)
Upvotes: 0