Swift Calendar Class Returning Wrong Date for Weekday

Swift Calendar class returning wrong date for weekday

Dates are always printed as if they are in the GMT timezone.

Suppose your time zone is UTC+1, then next Sunday will be 29-10-2017 00:00:00 in your time zone. However, this Date instance is expressed as 28-10-2017 23:00:00 in GMT.

So nextDate does return the correct date, it's just not formatted in your time zone. To fix this, just use a DateFormatter:

let formatter = DateFormatter()
formatter.dateStyle = .short
print(formatter.string(from: next_sunday))

Most concise fix for .weekday returning wrong day

In iOS, the weekdaySymbols starts from Sunday to Saturday. It's an array so indexes range from 0 to 6

All you need to do is subtract the weekDay number by 1 to get the right day like below:

let weekDay = Calendar.current.component(.weekday, from: Date())

let currentDay = DateFormatter().weekdaySymbols[weekDay-1]

Also, note that when you try to fetch the weekDay number for Sunday from Calendar API it will return you 1

Please find the developer documentation snapshot for a reference

Sample Image

Wrong date from components

It's because the date components you are providing are contradictory. You have weekDay 1 (which will probably be a Sunday or Monday, depending on your locale) but the 1 jan 2022 is a Saturday.

(you also used Calendar.default when I think you meant Calendar.current?)

If you take out the weekDay term you will get the correct answer:

Calendar.current.date(from: DateComponents(year: 2022, month: 1, hour: 16, minute: 1, second: 1, weekOfMonth: 1))

// "Jan 1, 2022 at 4:01 PM"

You could also remove the weekOfMonth term as it is superfluous when you are specifying the actual date.

Date() shows wrong time

From Apple's documentation:

A Date is independent of a particular calendar or time zone. To
represent a Date to a user, you must interpret it in the context of a
Calendar.

You need the help of Calendar:

let calendar = Calendar(identifier: .gregorian)
let currentDate = Date()
print(calendar.dateComponents(in: calendar.timeZone, from: currentDate))

the output will be:

calendar: gregorian (fixed) timeZone: Europe/Bratislava (current) era: 1 year: 2019 
month: 11 day: 19 hour: 15 minute: 47 second: 14 nanosecond: 285109996 weekday: 3 weekdayOrdinal: 3 quarter: 0 weekOfMonth: 4 weekOfYear: 47 yearForWeekOfYear: 2019 isLeapMonth: false

So you could then access your calendar's components like hour, minute etc.

UPDATE:

@Camile answered in comments to their question using DateFormatter:

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss:Z"
dateFormatter.timeZone = calendar.timeZone
dateFormatter.string(from:currentDate)

will give you

2019-11-19 16:38:03:+0100

Get day of week using NSDate

What you are looking for (if I understand the question correctly) is NSCalendarUnit.CalendarUnitWeekday. The corresponding property of NSDateComponents is weekday.

Note also that your date format is wrong (the
full specification can be found here: http://unicode.org/reports/tr35/tr35-6.html).

The function can be simplified slightly, using automatic type inference, also you use variables a lot where constants are sufficient.
In addition, the function should return an optional which is nil
for an invalid input string.

Updated code for Swift 3 and later:

func getDayOfWeek(_ today:String) -> Int? {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
guard let todayDate = formatter.date(from: today) else { return nil }
let myCalendar = Calendar(identifier: .gregorian)
let weekDay = myCalendar.component(.weekday, from: todayDate)
return weekDay
}

Example:

if let weekday = getDayOfWeek("2014-08-27") {
print(weekday)
} else {
print("bad input")
}

Original answer for Swift 2:

func getDayOfWeek(today:String)->Int? {

let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
if let todayDate = formatter.dateFromString(today) {
let myCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let myComponents = myCalendar.components(.Weekday, fromDate: todayDate)
let weekDay = myComponents.weekday
return weekDay
} else {
return nil
}
}

Get the next weekday of Date()

Change

let day = start.dayNumberOfWeek

To

let day = start.dayNumberOfWeek()

Or even better

if let day = start.dayNumberOfWeek() {

(There will still be compile errors, but that should be enough to get you moving again.)

why is Calendar.current.firstWeekday == 2?

which I interpret as

I believe your interpretation is wrong. I'm not sure how the framework assigns the days of the week, but from your question I believe that they go 1 through 7, where 1 is Sunday, 2 is Monday and so on. These are static and don't change with your settings.

The firstWeekday property tells you what day of the week the week starts in your locale. In the US, which is the default locale, a week starts on Sunday.

You can't "fix this" because nothing is wrong, that property is there to provide you with information which is specially useful when drawing a calendar.

Swift - Get next date from a array of weekdays

Never use 86400 for date math, Calendar and IndexSethave powerful methods to do that:

// Put your weekday indexes in an `IndexSet`
let weekdaySet = IndexSet([1, 2, 4, 7]) // Sun, Mon, Wed and Sat

// Get the current calendar and the weekday from today
let calendar = Calendar.current
var weekday = calendar.component(.weekday, from: Date())

// Calculate the next index
if let nextWeekday = weekdaySet.integerGreaterThan(weekday) {
weekday = nextWeekday
} else {
weekday = weekdaySet.first!
}

// Get the next day matching this weekday
let components = DateComponents(weekday: weekday)
calendar.nextDate(after: Date(), matching: components, matchingPolicy: .nextTime)

Swift Calendar, Weekday starting on Monday instead Sunday

Create a custom Gregorian calendar and set the first weekday to Monday

var customCalendar = Calendar(identifier: .gregorian)
customCalendar.firstWeekday = 2


Related Topics



Leave a reply



Submit