How to get Monday's date of the current week in swift

谁都会走 提交于 2019-11-27 01:37:31

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!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!