简体   繁体   中英

How to get week start date and end date by using any Month and week number swift 3?

I have to implement graph so that I need to get week start date and weekend date if I will pass the date object and week number.

How can I achieve that I tried it but didn't get exactly?

Here below is my code:-

Weekday:-

//Day of week
func getDayOfWeek(today:String)->Int? {
    let formatter  = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    if let todayDate = formatter.date(from: today) {
        let myCalendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)!
        let myComponents = myCalendar.components(.weekday, from: todayDate)
        let weekDay = myComponents.weekday
        return weekDay
    } else {
        return nil
    }
}. 

extension Date {
  var millisecondsSince1970:Int {
      return Int((self.timeIntervalSince1970 * 1000.0).rounded())
  }

  init(milliseconds:Int) {
      self = Date(timeIntervalSince1970: TimeInterval(milliseconds / 1000))
  }

  func startOfWeek(weekday: Int?) -> Date {
      var cal = Calendar.current
      var component = cal.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)
      component.to12am()
      cal.firstWeekday = weekday ?? 1
      return cal.date(from: component)!
  }

  func endOfWeek(weekday: Int) -> Date {
      let cal = Calendar.current
      var component = DateComponents()
      component.weekOfYear = 1
      component.day = -1
      component.to12pm()
      return cal.date(byAdding: component, to: startOfWeek(weekday: weekday))!
   }
}

  internal extension DateComponents {
    mutating func to12am() {
      self.hour = 0
      self.minute = 0
      self.second = 0
  }

  mutating func to12pm(){
      self.hour = 23
      self.minute = 59
      self.second = 59
  }
}

This returns start- and end date for a given week number and date

func dayRangeOf(weekOfYear: Int, for date: Date) -> Range<Date>
{
    let calendar = Calendar.current
    let year = calendar.component(.yearForWeekOfYear, from: date)
    let startComponents = DateComponents(weekOfYear: weekOfYear, yearForWeekOfYear: year)
    let startDate = calendar.date(from: startComponents)!
    let endComponents = DateComponents(day:7, second: -1)
    let endDate = calendar.date(byAdding: endComponents, to: startDate)!
    return startDate..<endDate
}

print(dayRangeOf(weekOfYear: 12, for: Date()))

Consider that print displays the dates in UTC and the start date depends on the first weekday setting of the current locale.

Edit

A version to determine the range of a given week of month

func dayRangeOf(weekOfMonth: Int, year: Int, month: Int) -> Range<Date>? {
    let calendar = Calendar.current
    guard let startOfMonth = calendar.date(from: DateComponents(year:year, month:month)) else { return nil }
    var startDate = Date()
    if weekOfMonth == 1 {
        var interval = TimeInterval()
        guard calendar.dateInterval(of: .weekOfMonth, start: &startDate, interval: &interval, for: startOfMonth) else { return nil }
    } else {
        let nextComponents = DateComponents(year: year, month: month, weekOfMonth: weekOfMonth)
        guard let weekStartDate = calendar.nextDate(after: startOfMonth, matching: nextComponents, matchingPolicy: .nextTime) else {
            return nil
        }
        startDate = weekStartDate
    }
    let endComponents = DateComponents(day:7, second: -1)
    let endDate = calendar.date(byAdding: endComponents, to: startDate)!
    return startDate..<endDate
}

print(dayRangeOf(weekOfMonth: 5, year: 2017, month: 6))

The result type of the second version is an optional because there are a few calculations which could fail for example if the number of week in the particular month is out of range.

For anyone interested in this, it looks like OP confusing weekOfMonth and weekOfYear…

//: Playground - noun: a place where people can play

import UIKit

var str = "Hello, playground"

let cal = Calendar.current


let dateComponents = DateComponents(year: 2018, month: 3, day: 15)
let date = cal.date(from: dateComponents)!

func weekOfMonthStart(forDate date: Date) -> Date {
    var compsToWeekOfMonth = cal.dateComponents([.year, .month, .weekOfYear], from: date)
    compsToWeekOfMonth.day = cal.range(of: .day, in: .weekOfMonth, for: date)?.lowerBound
    return cal.date(from: compsToWeekOfMonth)!
}

Somebody mention an answer that will fail, so a test was included ;)

for i in 0...5000 {
    let newDate = cal.date(byAdding: DateComponents(day:i), to: date)!
    weekOfMonthStart(forDate: newDate)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM