I'm trying to get Monday's date of the current week. This is treated as the first day of the week in my table view. I also need to get Sunday's of the current week. This is treated as the last day of the week in my table view.
Current attempt:
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
calendar.firstWeekday = 1
//attempt to changefirstday
let dateFormatter = NSDateFormatter()
let theDateFormat = NSDateFormatterStyle.ShortStyle
let theTimeFormat = NSDateFormatterStyle.ShortStyle
dateFormatter.dateStyle = theDateFormat
dateFormatter.timeStyle = theTimeFormat
let currentDateComponents = calendar.components([.YearForWeekOfYear, .WeekOfYear ], fromDate: date)
let startOfWeek = calendar.dateFromComponents(currentDateComponents)
print("startOfWeek is \(startOfWeek)")
let stringDate = dateFormatter.stringFromDate(startOfWeek!)
print("string date is \(stringDate)") //This is returning Sunday's date
I wrote Date extensions to get Date for certain weekday and here is how easy it is to use with Swift 4,
Date.today().next(.monday) // Feb 12, 2018 at 12:00 AM
Date.today().next(.sunday) // Feb 11, 2018 at 12:00 AM
Date.today().previous(.sunday) // Feb 4, 2018 at 12:00 AM
Date.today().previous(.monday) // Feb 5, 2018 at 12:00 AM
Date.today().previous(.thursday) // Feb 1, 2018 at 12:00 AM
Date.today().next(.thursday) // Feb 15, 2018 at 12:00 AM
Date.today().previous(.thursday,
considerToday: true) // Feb 8, 2018 at 11:04 PM
Date.today().next(.monday)
.next(.sunday)
.next(.thursday) // Feb 22, 2018 at 12:00 AM
And here is Date extension for that,
extension Date {
static func today() -> Date {
return Date()
}
func next(_ weekday: Weekday, considerToday: Bool = false) -> Date {
return get(.Next,
weekday,
considerToday: considerToday)
}
func previous(_ weekday: Weekday, considerToday: Bool = false) -> Date {
return get(.Previous,
weekday,
considerToday: considerToday)
}
func get(_ direction: SearchDirection,
_ weekDay: Weekday,
considerToday consider: Bool = false) -> Date {
let dayName = weekDay.rawValue
let weekdaysName = getWeekDaysInEnglish().map { $0.lowercased() }
assert(weekdaysName.contains(dayName), "weekday symbol should be in form \(weekdaysName)")
let searchWeekdayIndex = weekdaysName.index(of: dayName)! + 1
let calendar = Calendar(identifier: .gregorian)
if consider && calendar.component(.weekday, from: self) == searchWeekdayIndex {
return self
}
var nextDateComponent = DateComponents()
nextDateComponent.weekday = searchWeekdayIndex
let date = calendar.nextDate(after: self,
matching: nextDateComponent,
matchingPolicy: .nextTime,
direction: direction.calendarSearchDirection)
return date!
}
}
// MARK: Helper methods
extension Date {
func getWeekDaysInEnglish() -> [String] {
var calendar = Calendar(identifier: .gregorian)
calendar.locale = Locale(identifier: "en_US_POSIX")
return calendar.weekdaySymbols
}
enum Weekday: String {
case monday, tuesday, wednesday, thursday, friday, saturday, sunday
}
enum SearchDirection {
case Next
case Previous
var calendarSearchDirection: Calendar.SearchDirection {
switch self {
case .Next:
return .forward
case .Previous:
return .backward
}
}
}
}
You can use calendar ISO8601 where the first weekday is Monday:
Swift 3 or later
var mondaysDate: Date {
return Calendar(identifier: .iso8601).date(from: Calendar(identifier: .iso8601).dateComponents([.yearForWeekOfYear, .weekOfYear], from: Date()))!
}
print(mondaysDate.description(with: .current)) // Monday, July 16, 2018 at 12:00:00 AM Brasilia Standard Time"
as an extension:
extension Calendar {
static let iso8601 = Calendar(identifier: .iso8601)
}
extension Date {
var currentWeekMonday: Date {
return Calendar.iso8601.date(from: Calendar.iso8601.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self))!
}
}
let currentWeekMonday = Date().currentWeekMonday
print(currentWeekMonday.description(with: .current)) // Monday, July 16, 2018 at 12:00:00 AM Brasilia Standard Time
Here is the extension I created, first it finds sunday and then it adds one day
extension Date {
var startOfWeek: Date? {
let gregorian = Calendar(identifier: .gregorian)
guard let sunday = gregorian.date(from: gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)) else { return nil }
return gregorian.date(byAdding: .day, value: 1, to: sunday)
}
}
Here's a simplified version of Sandeep's answer.
Usage:
Date().next(.monday)
Date().next(.monday, considerToday: true)
Date().next(.monday, direction: .backward)
Extension:
public func next(_ weekday: Weekday,
direction: Calendar.SearchDirection = .forward,
considerToday: Bool = false) -> Date
{
let calendar = Calendar(identifier: .gregorian)
let components = DateComponents(weekday: weekday.rawValue)
if considerToday &&
calendar.component(.weekday, from: self) == weekday.rawValue
{
return self
}
return calendar.nextDate(after: self,
matching: components,
matchingPolicy: .nextTime,
direction: direction)!
}
public enum Weekday: Int {
case sunday = 1, monday, tuesday, wednesday, thursday, friday, saturday
}
Try to use:
calendar.firstWeekday = 2
Edit
To be more specific: NSCalendar.currentCalendar()
returns user calendar. According to docs:
The returned calendar is formed from the settings for the current user’s chosen system locale overlaid with any custom settings the user has specified in System Preferences.
If you want always Monday as first day, I think you should use:
let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
calendar!.firstWeekday = 2
Addition to @Saneep answer
If you would like to get exact dateTime as per given/current date (lets say you wanted to convert Monday's dateTime -> 23-05-2016 12:00:00
to 23-05-2016 05:35:17
) then try this:
func convertDate(date: NSDate, toGivendate: NSDate) -> NSDate {
let calendar = NSCalendar.currentCalendar()
let comp = calendar.components([.Year, .Month, .Day, .Hour, .Minute, .Second], fromDate: toGivendate)
let hour = comp.hour
let minute = comp.minute
let second = comp.second
let dateComp = calendar.components([.Year, .Month, .Day], fromDate: date)
let year = dateComp.year
let month = dateComp.month
let day = dateComp.day
let components = NSDateComponents()
components.year = year
components.month = month
components.day = day
components.hour = hour
components.minute = minute
components.second = second
let newConvertedDate = calendar.dateFromComponents(components)
return newConvertedDate!
}
Swift 4 Solution
I have figured out according to my requirement, where I have find out dates for following.
1. Today
2. Tomorrow
3. This Week
4. This Weekend
5. Next Week
6. Next Weekend
So, I have created Date Extension
to get Dates of Current Week and Next Week.
CODE
extension Date {
func getWeekDates() -> (thisWeek:[Date],nextWeek:[Date]) {
var tuple: (thisWeek:[Date],nextWeek:[Date])
var arrThisWeek: [Date] = []
for i in 0..<7 {
arrThisWeek.append(Calendar.current.date(byAdding: .day, value: i, to: startOfWeek)!)
}
var arrNextWeek: [Date] = []
for i in 1...7 {
arrNextWeek.append(Calendar.current.date(byAdding: .day, value: i, to: arrThisWeek.last!)!)
}
tuple = (thisWeek: arrThisWeek,nextWeek: arrNextWeek)
return tuple
}
var tomorrow: Date {
return Calendar.current.date(byAdding: .day, value: 1, to: noon)!
}
var noon: Date {
return Calendar.current.date(bySettingHour: 12, minute: 0, second: 0, of: self)!
}
var startOfWeek: Date {
let gregorian = Calendar(identifier: .gregorian)
let sunday = gregorian.date(from: gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self))
return gregorian.date(byAdding: .day, value: 1, to: sunday!)!
}
func toDate(format: String) -> String {
let formatter = DateFormatter()
formatter.dateFormat = format
return formatter.string(from: self)
}
}
USAGE:
let arrWeekDates = Date().getWeekDates() // Get dates of Current and Next week.
let dateFormat = "MMM dd" // Date format
let thisMon = arrWeekDates.thisWeek.first!.toDate(format: dateFormat)
let thisSat = arrWeekDates.thisWeek[arrWeekDates.thisWeek.count - 2].toDate(format: dateFormat)
let thisSun = arrWeekDates.thisWeek[arrWeekDates.thisWeek.count - 1].toDate(format: dateFormat)
let nextMon = arrWeekDates.nextWeek.first!.toDate(format: dateFormat)
let nextSat = arrWeekDates.nextWeek[arrWeekDates.nextWeek.count - 2].toDate(format: dateFormat)
let nextSun = arrWeekDates.nextWeek[arrWeekDates.nextWeek.count - 1].toDate(format: dateFormat)
print("Today: \(Date().toDate(format: dateFormat))") // Sep 26
print("Tomorrow: \(Date().tomorrow.toDate(format: dateFormat))") // Sep 27
print("This Week: \(thisMon) - \(thisSun)") // Sep 24 - Sep 30
print("This Weekend: \(thisSat) - \(thisSun)") // Sep 29 - Sep 30
print("Next Week: \(nextMon) - \(nextSun)") // Oct 01 - Oct 07
print("Next Weekend: \(nextSat) - \(nextSun)") // Oct 06 - Oct 07
You can modify Extension
according to your need.
Thanks!
来源:https://stackoverflow.com/questions/33397101/how-to-get-mondays-date-of-the-current-week-in-swift