I need to get the List of dates for the given date of the week.
As an example :
If user select the random date from picker Like 2017-6-7,
I needs to get and display the dates of the week.
[2017-6-4, 2017-6-5, 2017-6-6, 2017-6-7, 2017-6-8, 2017-6-9, 2017-6-10]
I couldn't find any solution on the internet.
Thank you
Try this:
let dateInWeek = Date()//7th June 2017
let calendar = Calendar.current
let dayOfWeek = calendar.component(.weekday, from: dateInWeek)
let weekdays = calendar.range(of: .weekday, in: .weekOfYear, for: dateInWeek)!
let days = (weekdays.lowerBound ..< weekdays.upperBound)
.compactMap { calendar.date(byAdding: .day, value: $0 - dayOfWeek, to: dateInWeek) }
print(days)
It will give you this:
4 June 2017(Sunday)
5 June 2017
6 June 2017
7 June 2017
8 June 2017
9 June 2017
10 June 2017(Saturday)
Start fromMonday
The above is default behavior for my calendar that's why it is starting from Sunday.
If you want start from Monday then do this change:
let dayOfWeek = calendar.component(.weekday, from: dateInWeek) - 1
It depends on which locale your calendar is in.
This is a starting point using the date math skills of Calendar
var calendar = Calendar.current
calendar.firstWeekday = 1 // adjust first weekday if necessary
var startOfWeek = Date()
var interval : TimeInterval = 0.0
_ = calendar.dateInterval(of:.weekOfYear, start: &startOfWeek, interval: &interval, for: Date())
for i in 0..<7 {
print(calendar.date(byAdding: .day, value: i, to: startOfWeek)!)
}
You can use this.
let today = Date()
let weekStartDate = today.getWeekStartDate(fromDate: today)
for i in 0..<5 {
let nextDate = weekStartDate?.getNextDay(value: i, currentDate:weekStartDate)
}
func getWeekStartDate(fromDate : Date?) -> Date? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
if let date = fromDate {
var calendar = Calendar(identifier: .gregorian)
calendar.firstWeekday = 3
var startDate : Date = Date()
var interval : TimeInterval = 0
if calendar.dateInterval(of: .weekOfYear, start: &startDate, interval: &interval, for: date) {
print("Start of week is \(startDate)")
// prints "Start of week is 2017-01-01 06:00:00 +0000"
return startDate
}
}
return nil
}
func getNextDay(value : Int, currentDate : Date?) -> Date? {
let dayComponenet = NSDateComponents()
dayComponenet.day = value
let theCalendar = NSCalendar.current
let nextDate = theCalendar.date(byAdding: dayComponenet as DateComponents, to: currentDate!)
return nextDate
}
Hope this will help!.
I am new in iOS and programming and I need somehow to get an array from the first day of current month till today. And one array for past 3 months till today, but I have no idea how to do that, please any help or ideas?
I checked about this to get the first day of month:
extension Date {
func startOfMonth() -> Date? {
let comp: DateComponents = Calendar.current.dateComponents([.year, .month, .hour], from: Calendar.current.startOfDay(for: self))
return Calendar.current.date(from: comp)!
}
but it works only in a ViewController, what to do if do that in other part of my project? and also I have no idea how to iterate the array to get all the days between first day and today...
EDIT
I made something like this, but it gives ma an infinite loops.. what am I doing wrong?
func weatherDatesFromCurrentDayMonth() -> [Any] {
var date = Date()
let currentCalendar = Calendar.current
var dateComponents = DateComponents()
dateComponents.month = -1
// dateComponents.day = 1
let endingDate = Calendar.current.date(byAdding: dateComponents, to: date)
print("\(endingDate!)")
var datesArray = Array<Any>()
while date.compare(endingDate!) != ComparisonResult.orderedAscending
{
var dateComponents = DateComponents()
dateComponents.day = 1
date = Calendar.current.date(byAdding: dateComponents, to: date)!
datesArray.append(date)
print("\(datesArray)")
}
return [datesArray]
}
You're having an endless loop because at the beginning your endingDate is already one month ago and date is now. Since inside the loop you only increment date it will never always be after endingDate and thus your condition is always true
Try this code:
func weatherDatesFromCurrentDayMonth() -> [Date] {
let now = Date()
var currentDate = previousMonth(date: now)
var datesArray = [Date]()
while currentDate < now {
datesArray.append(currentDate)
currentDate = nextDay(date:currentDate)
}
print("result: \(datesArray)")
return datesArray
}
func nextDay(date: Date) -> Date {
var dateComponents = DateComponents()
dateComponents.day = 1
return Calendar.current.date(byAdding: dateComponents, to: date)!
}
func previousMonth(date: Date) -> Date {
var dateComponents = DateComponents()
dateComponents.month = -1
return Calendar.current.date(byAdding: dateComponents, to: date)!
}
I need to translate this function into swift.
Basically what does it get the 'n' day of the current week. So for example if i use it with NSDate().getWeekDay(0) it gives me Sun 11 Sept, and so on.
But seems rangeOfUnit no longer exists in Swift-3.
This was my previous implementation in Swift-2
extension NSDate {
func getWeekDay(day: Int) -> NSDate {
var beginningOfWeek: NSDate?
NSCalendar.currentCalendar().rangeOfUnit(NSCalendarUnit.WeekOfYear, startDate: &beginningOfWeek, interval: nil, forDate: self)
let comps = NSDateComponents()
comps.day = day
comps.minute = NSCalendar.currentCalendar().component(NSCalendarUnit.Minute, fromDate: self)
comps.hour = NSCalendar.currentCalendar().component(NSCalendarUnit.Hour, fromDate: self)
let nextDate = NSCalendar.currentCalendar().dateByAddingComponents(comps, toDate: beginningOfWeek!, options: .SearchBackwards)
return nextDate!
}
}
There is an alternative to get the start of the week which
translates directly to Swift 3:
extension Date {
func getWeekDay(day: Int) -> Date {
let cal = Calendar.current
let comps = cal.dateComponents([.weekOfYear, .yearForWeekOfYear], from: self)
let beginningOfWeek = cal.date(from: comps)!
let nextDate = cal.date(byAdding: .day, value: day, to: beginningOfWeek)!
return nextDate
}
}
This is your extension in Swift 3 for Date and a bit optimized
extension Date {
func getWeekDay(day: Int) -> Date {
var beginningOfWeek = Date()
var interval : TimeInterval = 0
let currentCalendar = Calendar.current
currentCalendar.dateInterval(of: .weekOfYear, start: &beginningOfWeek, interval: &interval, for: self)
return currentCalendar.date(byAdding: .day, value: day, to: beginningOfWeek)!
}
}
rangeOfUnit(startDate:interval:forDate:) has been turned into dateInterval(of:start:interval:for:) in the new Calendar structure.
I need the first and last date of the month using current date. I have found lots of solutions for this. But all gives me wrong answer.
My code:
1. First Date of the month
extension NSDate{
func firstDateOfMonth ()->NSDate{
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Year, .Month], fromDate: self)
let startOfMonth = calendar.dateFromComponents(components)!
return startOfMonth
}
func lastDateOfmonth()->NSDate{
let calendar = NSCalendar.currentCalendar()
let comps2 = NSDateComponents()
comps2.month = 1
comps2.day = -1
let endOfMonth = calendar.dateByAddingComponents(comps2, toDate: self, options: [])!
return endOfMonth
}
}
Result looks like this:
print(NSDate().firstDateOfMonth())
print(NSDate().lastDateOfmonth())
Output:
2016-01-31 18:30:00 +0000 // instead of 2016-02-01
// prints the previous month last date
2016-03-02 06:56:17 +0000 // instead of 2016-02-29
// next month date
Please correct if anything is wrong
And I tried this code also
extension NSDate{
func firstDateOfMonths ()->NSDate{
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Era, .Year,.Month], fromDate: self)
components.day = 1
let startOfMonth = calendar.dateFromComponents(components)!
return startOfMonth
}
}
Thanks
The first problem is the common problem that you don't understand how NSDate works. NSDate returns UTC, not a date in your time zone. There are hundreds of questions explaining this.
The second problem is you being careless by getting all date components. You are adding one month minus one day to the current date.
The most reliable way to calculate days is rangeOfUnit of NSCalendar
extension NSDate {
func firstDateOfMonth() -> NSDate {
let calendar = NSCalendar.currentCalendar()
// calendar.timeZone = NSTimeZone(forSecondsFromGMT: 0) use this line if you need UTC
var startDate : NSDate?
calendar.rangeOfUnit(.Month, startDate: &startDate, interval: nil, forDate: self)
return startDate!
}
func lastDateOfMonth() -> NSDate {
let calendar = NSCalendar.currentCalendar()
// calendar.timeZone = NSTimeZone(forSecondsFromGMT: 0) use this line if you need UTC
let dayRange = calendar.rangeOfUnit(.Day, inUnit: .Month, forDate: self)
let dayLength = dayRange.length
let components = calendar.components([.Year, .Month, .Day], fromDate: self)
components.day = dayLength
return calendar.dateFromComponents(components)!
}
}
Swift 3+
In Calendar the API is named dateInterval(of:start:interval:for:
extension Date {
func firstDateOfMonth() -> Date {
let calendar = Calendar.current
var startDate = Date()
var interval : TimeInterval = 0
_ = calendar.dateInterval(of:.month, start: &startDate, interval: &interval, for: self)
return startDate
}
func lastDateOfMonth() -> Date {
let calendar = Calendar.current
let dayRange = calendar.range(of:.day, in: .month, for: self)!
let dayLength = dayRange.upperBound
var components = calendar.dateComponents([.year, .month, .day], from: self)
components.day = dayLength
return calendar.date(from:components)!
}
}
I'm trying to get the first and last day of the month in swift.
So far I have the following:
let dateFormatter = NSDateFormatter()
let date = NSDate()
dateFormatter.dateFormat = "yyyy-MM-dd"
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Year, .Month, .Day, .Hour, .Minute, .Second], fromDate: date)
let month = components.month
let year = components.year
let startOfMonth = ("\(year)-\(month)-01")
But I'm not sure how to get the last date. Is there a built in method I'm missing? Obviously it has to take into account leap years etc.
Swift 3 and 4 drop-in extensions
This actually gets a lot easier with Swift 3+:
You can do it without guard (you could if you wanted to, but because DateComponents is a non-optional type now, it's no longer necessary).
Using iOS 8's startOfDayForDate (now startOfDay), you don't need to manually set the time to 12pm unless you're doing some really crazy calendar calculations across time zones.
It's worth mentioning that some of the other answers claim you can shortcut this by using Calendar.current.date(byAdding: .month, value: 0, to: Date())!, but where this fails, is that it doesn't actually zero out the day, or account for differences in timezones.
Here you go:
extension Date {
func startOfMonth() -> Date {
return Calendar.current.date(from: Calendar.current.dateComponents([.year, .month], from: Calendar.current.startOfDay(for: self)))!
}
func endOfMonth() -> Date {
return Calendar.current.date(byAdding: DateComponents(month: 1, day: -1), to: self.startOfMonth())!
}
}
print(Date().startOfMonth()) // "2018-02-01 08:00:00 +0000\n"
print(Date().endOfMonth()) // "2018-02-28 08:00:00 +0000\n"
You get the first day of the month simply with
let components = calendar.components([.Year, .Month], fromDate: date)
let startOfMonth = calendar.dateFromComponents(components)!
print(dateFormatter.stringFromDate(startOfMonth)) // 2015-11-01
To get the last day of the month, add one month and subtract one day:
let comps2 = NSDateComponents()
comps2.month = 1
comps2.day = -1
let endOfMonth = calendar.dateByAddingComponents(comps2, toDate: startOfMonth, options: [])!
print(dateFormatter.stringFromDate(endOfMonth)) // 2015-11-30
Alternatively, use the rangeOfUnit method which gives you
the start and the length of the month:
var startOfMonth : NSDate?
var lengthOfMonth : NSTimeInterval = 0
calendar.rangeOfUnit(.Month, startDate: &startOfMonth, interval: &lengthOfMonth, forDate: date)
For a date on the last day of month, add the length of the month minus one second:
let endOfMonth = startOfMonth!.dateByAddingTimeInterval(lengthOfMonth - 1)
Updated for Swift5:
extension Date {
var startOfDay: Date {
return Calendar.current.startOfDay(for: self)
}
var startOfMonth: Date {
let calendar = Calendar(identifier: .gregorian)
let components = calendar.dateComponents([.year, .month], from: self)
return calendar.date(from: components)!
}
var endOfDay: Date {
var components = DateComponents()
components.day = 1
components.second = -1
return Calendar.current.date(byAdding: components, to: startOfDay)!
}
var endOfMonth: Date {
var components = DateComponents()
components.month = 1
components.second = -1
return Calendar(identifier: .gregorian).date(byAdding: components, to: startOfMonth)!
}
func isMonday() -> Bool {
let calendar = Calendar(identifier: .gregorian)
let components = calendar.dateComponents([.weekday], from: self)
return components.weekday == 2
}
}
With Swift 3 & iOS 10 the easiest way I found to do this is Calendar's dateInterval(of:for:):
guard let interval = calendar.dateInterval(of: .month, for: Date()) else { return }
You can then use interval.start and interval.end to get the dates you need.
Swift 3
Many date example for :
Last 6 month,
last 3 month,
yesterday, last 7 day, last 30 day, previous month,
current month start & end, last month start & end date
let startDate = dateFormatter.string(from: Date().getThisMonthStart()!)
let endDate = dateFormatter.string(from: Date().getThisMonthEnd()!)
extension Date {
func getLast6Month() -> Date? {
return Calendar.current.date(byAdding: .month, value: -6, to: self)
}
func getLast3Month() -> Date? {
return Calendar.current.date(byAdding: .month, value: -3, to: self)
}
func getYesterday() -> Date? {
return Calendar.current.date(byAdding: .day, value: -1, to: self)
}
func getLast7Day() -> Date? {
return Calendar.current.date(byAdding: .day, value: -7, to: self)
}
func getLast30Day() -> Date? {
return Calendar.current.date(byAdding: .day, value: -30, to: self)
}
func getPreviousMonth() -> Date? {
return Calendar.current.date(byAdding: .month, value: -1, to: self)
}
// This Month Start
func getThisMonthStart() -> Date? {
let components = Calendar.current.dateComponents([.year, .month], from: self)
return Calendar.current.date(from: components)!
}
func getThisMonthEnd() -> Date? {
let components:NSDateComponents = Calendar.current.dateComponents([.year, .month], from: self) as NSDateComponents
components.month += 1
components.day = 1
components.day -= 1
return Calendar.current.date(from: components as DateComponents)!
}
//Last Month Start
func getLastMonthStart() -> Date? {
let components:NSDateComponents = Calendar.current.dateComponents([.year, .month], from: self) as NSDateComponents
components.month -= 1
return Calendar.current.date(from: components as DateComponents)!
}
//Last Month End
func getLastMonthEnd() -> Date? {
let components:NSDateComponents = Calendar.current.dateComponents([.year, .month], from: self) as NSDateComponents
components.day = 1
components.day -= 1
return Calendar.current.date(from: components as DateComponents)!
}
}
Swift 4
If you only need the ordinal day:
func lastDay(ofMonth m: Int, year y: Int) -> Int {
let cal = Calendar.current
var comps = DateComponents(calendar: cal, year: y, month: m)
comps.setValue(m + 1, for: .month)
comps.setValue(0, for: .day)
let date = cal.date(from: comps)!
return cal.component(.day, from: date)
}
lastDay(ofMonth: 2, year: 2018) // 28
lastDay(ofMonth: 2, year: 2020) // 29
This is the simplest way that I found (Swift 5+):
extension Date {
func getStart(of component: Calendar.Component, calendar: Calendar = Calendar.current) -> Date? {
return calendar.dateInterval(of: component, for: self)?.start
}
func getEnd(of component: Calendar.Component, calendar: Calendar = Calendar.current) -> Date? {
return calendar.dateInterval(of: component, for: self)?.end
}
}
Here is easiest solution:
extension Date {
func startOfMonth() -> Date {
let interval = Calendar.current.dateInterval(of: .month, for: self)
return (interval?.start.toLocalTime())! // Without toLocalTime it give last months last date
}
func endOfMonth() -> Date {
let interval = Calendar.current.dateInterval(of: .month, for: self)
return interval!.end
}
// Convert UTC (or GMT) to local time
func toLocalTime() -> Date {
let timezone = TimeZone.current
let seconds = TimeInterval(timezone.secondsFromGMT(for: self))
return Date(timeInterval: seconds, since: self)
}}
and then call these with your date instance:
print(Date().startOfMonth())
print(Date().endOfMonth())
2017...
First, get the month you need:
let cal = Calendar.current
let d = Calendar.current.date(byAdding: .month, value: 0, to: Date())!
// for "last month" just use -1, for "next month" just use 1, etc
To get the day-of-the-week for the first day of the month:
let c = cal.dateComponents([.year, .month], from: d)
let FDOM = cal.date(from: c)!
let dowFDOM = cal.component(.weekday, from: FDOM)
print("the day-of-week on the 1st is ... \(dowFDOM)")
// so, that's 1=Sunday, 2=Monday, etc.
To get the number of days in the month:
let r = cal.range(of: .day, in: .month, for: d)!
let kDays = r.count
print("the number of days is ... \(kDays)")
With Swift 3, you can choose one of the two following patters in order to retrieve the first and last days of a month.
#1. Using Calendar dateComponents(_:from:), date(from:) and date(byAdding:to:wrappingComponents:) methods
With this pattern, you first get the date of the first day of a month then add a month and remove a day from it in order to get the date of the last day of the month. The Playground code below shows how to set it:
import Foundation
// Set calendar and date
let calendar = Calendar.current
let date = calendar.date(byAdding: DateComponents(day: -10), to: Date())!
// Get first day of month
let firstDayComponents = calendar.dateComponents([.year, .month], from: date)
let firstDay = calendar.date(from: firstDayComponents)!
// Get last day of month
let lastDayComponents = DateComponents(month: 1, day: -1)
let lastDay = calendar.date(byAdding: lastDayComponents, to: firstDay)!
// Set date formatter
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_UK")
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .long
// Print results
print(dateFormatter.string(from: date)) // Prints: 22 March 2017 at 18:07:15 CET
print(dateFormatter.string(from: firstDay)) // Prints: 1 March 2017 at 00:00:00 CET
print(dateFormatter.string(from: lastDay)) // Prints: 31 March 2017 at 00:00:00 CEST
#2. Using Calendar range(of:in:for:), dateComponents(_:from:) and date(from:) and methods
With this pattern, you get a range of absolute day values in a month and then retrieve the dates of the first day and last day of the month from it. The Playground code below shows how to set it:
import Foundation
// Set calendar and date
let calendar = Calendar.current
let date = calendar.date(byAdding: DateComponents(day: -10), to: Date())!
// Get range of days in month
let range = calendar.range(of: .day, in: .month, for: date)! // Range(1..<32)
// Get first day of month
var firstDayComponents = calendar.dateComponents([.year, .month], from: date)
firstDayComponents.day = range.lowerBound
let firstDay = calendar.date(from: firstDayComponents)!
// Get last day of month
var lastDayComponents = calendar.dateComponents([.year, .month], from: date)
lastDayComponents.day = range.upperBound - 1
//lastDayComponents.day = range.count // also works
let lastDay = calendar.date(from: lastDayComponents)!
// Set date formatter
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_UK")
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .long
// Print results
print(dateFormatter.string(from: date)) // prints: 22 March 2017 at 18:07:15 CET
print(dateFormatter.string(from: firstDay)) // prints: 1 March 2017 at 00:00:00 CET
print(dateFormatter.string(from: lastDay)) // prints: 31 March 2017 at 00:00:00 CEST
In swift 3, if you put 0 to day component you can get the last day of the month. There's an example code:
public func isMoreDays(date: Date, asc: Bool)->Bool{
//components
var dayComponents = self.getDateComponents(date: date)
//asc is true if ascendant or false if descendant
dayComponents.day = asc ? 0 : 1
//plus 1 to month 'cos if you set up day to 0 you are going to the previous month
dayComponents.month = asc ? dayComponents.month! + 1 : dayComponents.month
//instantiate calendar and get the date
let calendar : Calendar = NSCalendar.current
let day = calendar.date(from: dayComponents)
//date comparison
if(day?.compare(date) == .orderedSame){
return false
}
return true
}
You can use the following extensions here :
let today = Date()
let startOfMonth = today.beginning(of: .month)
let endOfMonth = today.end(of: .month)