【问题标题】:How to get Monday's date of the current week in swift如何快速获取本周的星期一日期
【发布时间】:2016-01-28 14:00:23
【问题描述】:

我正在尝试获取本周的星期一日期。在我的表格视图中,这被视为一周的第一天。 我还需要获取本周的星期日。这在我的表格视图中被视为一周的最后一天。

当前尝试:

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

【问题讨论】:

  • 您可以使用日历 ISO8601,其中第一个工作日是星期一,不要将 firstWeekday 更改为 1(星期日) let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)!
  • 你的问题我不清楚。如果您设置calendar.firstWeekday = 1,则星期日被定义为一周的第一天,因此您的结果是可以预期的。

标签: swift date nscalendar


【解决方案1】:

我编写了日期扩展来获取某个工作日的日期,这是使用 Swift 5 的简单程度,

Date.today()                                  // Oct 15, 2019 at 9:21 AM
Date.today().next(.monday)                    // Oct 21, 2019 at 9:21 AM
Date.today().next(.sunday)                    //  Oct 20, 2019 at 9:21 AM


Date.today().previous(.sunday)                // Oct 13, 2019 at 9:21 AM
Date.today().previous(.monday)                // Oct 14, 2019 at 9:21 AM

Date.today().previous(.thursday)              // Oct 10, 2019 at 9:21 AM
Date.today().next(.thursday)                  // Oct 17, 2019 at 9:21 AM
Date.today().previous(.thursday,
                      considerToday: true)    // Oct 10, 2019 at 9:21 AM


Date.today().next(.monday)
            .next(.sunday)
            .next(.thursday)                  // Oct 31, 2019 at 9:21 AM

这里是日期扩展,

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.firstIndex(of: dayName)! + 1

    let calendar = Calendar(identifier: .gregorian)

    if consider && calendar.component(.weekday, from: self) == searchWeekdayIndex {
      return self
    }

    var nextDateComponent = calendar.dateComponents([.hour, .minute, .second], from: self)
    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
      }
    }
  }
}

【讨论】:

  • 为了在本周末(本周的情况下为 11 月 1 日)获得星期天,我进行了哪些更改?
  • 现在我可以使用 get(.Previous, "Monday") 获取本周的星期一,并使用 get(.Next, "Sunday", thinkToday: true) 成功获取星期天本周。如果一周从星期一开始,在星期日结束。这就是我需要的,但我还需要下周一和下周日。所以我可以使用你的 get(.Next, "Monday") 来获得下周的星期一,但我无法获得下周的星期日。这个可以吗?
  • 要获得确切的时间,不仅是凌晨 12:00,请查看我的回答。
  • 如果我有2018-04-02 并要求上周日,它给了我2018-03-25 而不是2018-04-01
  • 你怎么看日期?登录到 XCode 控制台?查看时区,可能是它为原始时区提供了正确的日期,而不是打印的那个。
【解决方案2】:

您可以使用日历 ISO8601,其中第一个工作日是星期一:

Swift 5.2 或更高版本

extension Calendar {
    static let iso8601 = Calendar(identifier: .iso8601)
    static let iso8601UTC: Calendar = {
        var calendar = Calendar(identifier: .iso8601)
        calendar.timeZone = TimeZone(identifier: "UTC")!
        return calendar
    }()
}

let monday =
    Calendar.iso8601.dateComponents([.calendar, .yearForWeekOfYear, .weekOfYear], from: Date()).date!  // "Nov 9, 2020 at 12:00 AM"
print(monday.description(with: .current))   // "Monday, November 9, 2020 at 12:00:00 AM Brasilia Standard Time\n"
let mondayUTC =
    Calendar.iso8601UTC.dateComponents([.calendar, .yearForWeekOfYear, .weekOfYear], from: Date()).date!  // "Nov 8, 2020 at 9:00 PM" TimeZone -03:00
print(mondayUTC)   // "2020-11-09 00:00:00 +0000\n"

作为 Date 计算机属性扩展实现:

extension Date {
    var mondayOfTheSameWeek: Date {
        Calendar.iso8601.dateComponents([.calendar, .yearForWeekOfYear, .weekOfYear], from: self).date!
    }
    var mondayOfTheSameWeekAtUTC: Date {
        Calendar.iso8601UTC.dateComponents([.calendar, .yearForWeekOfYear, .weekOfYear], from: self).date!
    }
}

let mondayOfTheSameWeek = Date().mondayOfTheSameWeek   // "Nov 9, 2020 at 12:00 AM"
print(mondayOfTheSameWeek.description(with: .current)) // "Monday, November 9, 2020 at 12:00:00 AM Brasilia Standard Time\n"
let mondayOfTheSameWeekAtUTC = Date().mondayOfTheSameWeekAtUTC  // "Nov 8, 2020 at 9:00 PM"
print(mondayOfTheSameWeekAtUTC) // "2020-11-09 00:00:00 +0000\n"

【讨论】:

  • 完美答案,时区小修正。 var comp: DateComponents = Calendar(identifier: .iso8601).dateComponents([.yearForWeekOfYear, .weekOfYear], from: Date()) comp.timeZone = TimeZone(secondsFromGMT: 0) let mondayDate = Calendar(identifier: .iso8601).date(from: comp)! print("Monday \(mondayDate)")
【解决方案3】:

这是Sandeep's answer 的简化版本。

用法:

Date().next(.monday)
Date().next(.monday, considerToday: true)
Date().next(.monday, direction: .backward)

扩展名:

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
}

【讨论】:

  • WeekDay不是以Sunday开头会正确吗?
  • @TheTiger 无论系统偏好如何,它都可以工作,但您不能更改枚举。
【解决方案4】:

这是我创建的扩展,首先它找到了星期天,然后它添加了一天

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)
    }
}

【讨论】:

  • 不错的扩展,但添加的值不应该是 2 作为.firstWeekday 吗?如果我使用值 1,它将提供星期日的日期...return gregorian.date(byAdding: .day, value: 2, to: sunday)
  • 我不知道你为什么会得到星期天。我刚试过并得到了一个星期一swift.sandbox.bluemix.net/#/repl/598b2f8308bc28326a66e302
  • 我认为你应该使用 gregorian.firstWeekday 而不是 1 或 2
  • 这个问题是:如果是星期天,这个扩展将返回明天的日期。如果您认为星期日是最后一天,那么您应该得到前一个星期一,而不是下一个星期一。
【解决方案5】:

尝试使用:

calendar.firstWeekday = 2

编辑

更具体地说:NSCalendar.currentCalendar() 返回用户日历。根据文档:

返回的日历由当前用户选择的系统区域设置与用户在“系统偏好设置”中指定的任何自定义设置叠加而成。

如果您希望始终将星期一作为第一天,我认为您应该使用:

let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
calendar!.firstWeekday = 2

【讨论】:

    【解决方案6】:

    @Saneep 答案的补充

    如果您想根据给定/当前日期获取确切的 dateTime(假设您想将星期一的 dateTime -> 23-05-2016 12:00:00 转换为 23-05-2016 05:35:17),请尝试以下操作:

    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!
    }
    

    【讨论】:

      【解决方案7】:

      Swift 4 解决方案

      我已经根据我的要求想通了,我在哪里找到了关注的日期。

      1. Today
      
      2. Tomorrow 
      
      3. This Week 
      
      4. This Weekend 
      
      5. Next Week 
      
      6. Next Weekend
      

      所以,我创建了Date Extension 来获取当前周下周的日期。

      代码

      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)
          }
      }
      

      用法:

      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
      

      您可以根据需要修改Extension

      谢谢!

      【讨论】:

        【解决方案8】:

        简单的代码(记住要更好地照顾选项):

        let now = Date()
        
        var calendar = Calendar(identifier: .gregorian)
        
        let timeZone = TimeZone(identifier: "UTC")!
        
        let desiredWeekDay = 2
        
        let weekDay = calendar.component(.weekday, from: now)
        var weekDayDate = calendar.date(bySetting: .weekday, value: desiredWeekDay, of: now)!
        
        /// Swift will give back the closest day matching the value above so we need to manipulate it to be always included at cuurent week.
        if weekDayDate > now, weekDay > desiredWeekDay {
            weekDayDate = weekDayDate - 7*24*60*60
        }
        
        print(weekDayDate)
        

        【讨论】:

        • 并非每个日期都有 24 小时
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多