Date range betwen now and end of the day and next day and end of the next day - swift

I'm trying to make a DatePicker with a choice between today and tomorrow. Two buttons to switch Date Range.
How to make today range? i. e. Now -> End of the day
How to make tomorrow range? i. e. Start of the next day -> End of the next day
what i've tried, but it's not correct
var todayRange: ClosedRange<Date> {
let calendar = Calendar.current
var endComponents = DateComponents()
endComponents.day = 1
let endDate = calendar.date(byAdding: endComponents, to: Date.now)!
return Date.now ... endDate
}
var tommorowRange: ClosedRange<Date> {
let calendar = Calendar.current
var startComponents = DateComponents()
startComponents.day = 2
var endComponents = DateComponents()
endComponents.day = 1
let startDate = calendar.date(byAdding: startComponents, to: Date.now)!
let endDate = calendar.date(byAdding: endComponents, to: startDate)!
return startDate ... endDate
}

You're close.
I would suggest:
Get the start of day for today
Add 1 day
Subtract 0.001 seconds.
That will give you the end of today.
Here is some sample code.
let today = Date.now
let startOfToday = Calendar.current.startOfDay(for: today)
let oneDay = DateComponents(day: 1)
guard let tomorrow = Calendar.current.date(byAdding: oneDay, to: startOfToday) else { fatalError() }
let endOfToday = tomorrow.advanced(by: -0.001)
let endOfTodayString = DateFormatter.localizedString(from: endOfToday, dateStyle: .medium, timeStyle: .medium)
print("End of today = " + endOfTodayString)
guard let endOfTomorrow = Calendar.current.date(byAdding: oneDay, to: endOfToday) else { fatalError() }
let endOfTomorrowString = DateFormatter.localizedString(from: endOfToday, dateStyle: .medium, timeStyle: .medium)
print("End of tomorrow = " + endOfTomorrowString)
In my locale (US), on October 7th, that generates:
End of today = Oct 7, 2022 at 11:59:59 PM
End of tomorrow = Oct 7, 2022 at 11:59:59 PM

Related

How to round up date to midnight in Swift? [duplicate]

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)

How to have reoccurring countdown each year to a date in Swift

I am trying to incorporate a countdown to a holiday within my app in Swift and having trouble with the timer going into negative numbers once the date has passed. The countdown should reset after the date passing. What am I doing wrong?
var holidayDate: Date {
let currentYear = Date()
let userCalendar = Calendar.current
var components = DateComponents()
components.year = userCalendar.component(.year, from: currentYear)
components.day = 02
components.month = 11
return userCalendar.date(from: components)!
}
var today: Date {
let now = Date()
let userCalendar = Calendar.current
var components = DateComponents()
components.year = userCalendar.component(.year, from: now)
components.day = userCalendar.component(.day, from: now)
components.month = userCalendar.component(.month, from: now)
return userCalendar.date(from: components)!
}
func daysBetweenDates(startDate: Date, endDate: Date) -> Int {
let calendar = Calendar.current
let components = calendar.dateComponents([.day], from: startDate, to: endDate)
return components.day!
}
You can simply use calendar nextDate method to get the next date matching components and pass the month and day components to it:
func daysUntilNextDate(matching components: DateComponents) -> Int {
let date = Date()
guard let calendar = components.calendar,
let nextDate = calendar.nextDate(after: date, matching: components, matchingPolicy: .strict) else { return .zero }
return calendar.dateComponents([.day], from: date, to: nextDate).day!
}
let holiday: DateComponents = .init(calendar: .current, month: 11, day: 2)
let christmas: DateComponents = .init(calendar: .current, month: 12, day: 25)
daysUntilNextDate(matching: holiday) // 363
daysUntilNextDate(matching: christmas) // 51

How to calculate the difference in days for two Date in Swift as days start at 6 a.m. instead of 0

I'm trying to get the difference in two Date objects.
I know how to do it basically, which is like this:
let date = Date()
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale.current
print(count)
// print(history[count - 1].value(forKey: "multipleURLs") as! [String])
let latestDate = history[count - 1].value(forKey: "date") as! Date
let calendar = Calendar.current
let components = calendar.dateComponents([.year, .month, .day, .hour], from: date)
let nowDate = calendar.startOfDay(for: date)
let lastDate = calendar.startOfDay(for: latestDate)
let diffDateComponent = (calendar as NSCalendar).components([NSCalendar.Unit.year, NSCalendar.Unit.month, NSCalendar.Unit.day], from: lastDate, to: nowDate, options: NSCalendar.Options.init(rawValue: 0))
print("Status Checked" + String(describing: diffDateComponent.day))
But I'm trying to get the result as a day start from 6 a.m. in the morning instead of 0.
So I did something like this:
let nowDate = calendar.startOfDay(for: date.addingTimeInterval(-3600))
let lastDate = calendar.startOfDay(for: latestDate.addingTimeInterval(-3600))
But it doesn't seem to be working, can anyone help me with this?
This will set each date to 6 AM (in the current locale of the Date):
import Foundation
// set up dates
let calendar = Calendar.current
let date = Date()
if let latestDate = calendar.date(byAdding: .day, value: -5, to: date) {
// set each day to 6 AM
if let nowDate = calendar.date(bySettingHour: 6, minute: 0, second: 0, of: date ),
let lastDate = calendar.date(bySettingHour: 6, minute: 0, second: 0, of: latestDate) {
print( date.description(with: .current),
nowDate.description(with: .current),
lastDate.description(with: .current),
separator: "\n")
// calculate difference in days
if let days = calendar.dateComponents([.day], from: lastDate, to: nowDate).day {
print("Days since: \(days)")
}
}
}
// Thursday, June 8, 2017 at 7:59:42 AM Eastern Daylight Time
// Thursday, June 8, 2017 at 6:00:00 AM Eastern Daylight Time
// Saturday, June 3, 2017 at 6:00:00 AM Eastern Daylight Time
// Days since: 5
Thanks guy, I finally figured it out. In case anyone need it, this is how it's done:
let date = Date()
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale.current
let latestDate = history[count - 1].value(forKey: "date") as! Date
let calendar = Calendar.current
let nowDate = calendar.date(byAdding: .hour, value: -6, to: date)
let lastDate = calendar.date(byAdding: .hour, value: -6, to: latestDate)
let finalNowDate = calendar.startOfDay(for: nowDate!)
let finalLastDate = calendar.startOfDay(for: lastDate!)
let diffDateComponent = calendar.dateComponents([.day], from: finalLastDate, to: finalNowDate)
print("dif\(diffDateComponent.day)")

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

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 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
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.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
}
}
}
}
You can use calendar ISO8601 where the first weekday is Monday:
Swift 5.2 or later
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"
Implemented as a Date computer property extension:
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"
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
}
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)
}
}
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
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!
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!
}
simple code (remember to take better care of the optionals):
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)

How do I find the number of days in given month and year using swift

I want to find the total number days on given month and year.
Example: I want to find total number of days on year = 2015, month = 7
First create an NSDate for the given year and month:
let dateComponents = NSDateComponents()
dateComponents.year = 2015
dateComponents.month = 7
let calendar = NSCalendar.currentCalendar()
let date = calendar.dateFromComponents(dateComponents)!
Then use the rangeOfUnit() method, as described in
Number of days in the current month using iPhone SDK?:
// Swift 2:
let range = calendar.rangeOfUnit(.Day, inUnit: .Month, forDate: date)
// Swift 1.2:
let range = calendar.rangeOfUnit(.CalendarUnitDay, inUnit: .CalendarUnitMonth, forDate: date)
let numDays = range.length
print(numDays) // 31
Update for Swift 3 (Xcode 8):
let dateComponents = DateComponents(year: 2015, month: 7)
let calendar = Calendar.current
let date = calendar.date(from: dateComponents)!
let range = calendar.range(of: .day, in: .month, for: date)!
let numDays = range.count
print(numDays) // 31
Updated for Swift 3.1, Xcode 8+, iOS 10+
let calendar = Calendar.current
let date = Date()
// Calculate start and end of the current year (or month with `.month`):
let interval = calendar.dateInterval(of: .year, for: date)! //change year it will no of days in a year , change it to month it will give no of days in a current month
// Compute difference in days:
let days = calendar.dateComponents([.day], from: interval.start, to: interval.end).day!
print(days)
In extension format, using self to be able to return the number of days more dynamically (Swift 3).
extension Date {
func getDaysInMonth() -> Int{
let calendar = Calendar.current
let dateComponents = DateComponents(year: calendar.component(.year, from: self), month: calendar.component(.month, from: self))
let date = calendar.date(from: dateComponents)!
let range = calendar.range(of: .day, in: .month, for: date)!
let numDays = range.count
return numDays
}
}
Swift 5.0
func getDaysInMonth(month: Int, year: Int) -> Int? {
let calendar = Calendar.current
var startComps = DateComponents()
startComps.day = 1
startComps.month = month
startComps.year = year
var endComps = DateComponents()
endComps.day = 1
endComps.month = month == 12 ? 1 : month + 1
endComps.year = month == 12 ? year + 1 : year
let startDate = calendar.date(from: startComps)!
let endDate = calendar.date(from:endComps)!
let diff = calendar.dateComponents([Calendar.Component.day], from: startDate, to: endDate)
return diff.day
}
if let numberOfDays = getDaysInMonth(month: 1, year: 2015) {
print(numberOfDays)
}
Swift 2.0
func getDaysInMonth(month: Int, year: Int) -> Int
{
let calendar = NSCalendar.currentCalendar()
let startComps = NSDateComponents()
startComps.day = 1
startComps.month = month
startComps.year = year
let endComps = NSDateComponents()
endComps.day = 1
endComps.month = month == 12 ? 1 : month + 1
endComps.year = month == 12 ? year + 1 : year
let startDate = calendar.dateFromComponents(startComps)!
let endDate = calendar.dateFromComponents(endComps)!
let diff = calendar.components(NSCalendarUnit.Day, fromDate: startDate, toDate: endDate, options: NSCalendarOptions.MatchFirst)
return diff.day
}
let days = getDaysInMonth(4, year: 2015) // April 2015 has 30 days
print(days) // Prints 30
Swift 1.2
func getDaysInMonth(month: Int, year: Int) -> Int
{
let calendar = NSCalendar.currentCalendar()
let startComps = NSDateComponents()
startComps.day = 1
startComps.month = month
startComps.year = year
let endComps = NSDateComponents()
endComps.day = 1
endComps.month = month == 12 ? 1 : month + 1
endComps.year = month == 12 ? year + 1 : year
let startDate = calendar.dateFromComponents(startComps)!
let endDate = calendar.dateFromComponents(endComps)!
let diff = calendar.components(NSCalendarUnit.CalendarUnitDay, fromDate: startDate, toDate: endDate, options: NSCalendarOptions.allZeros)
return diff.day
}
let days = getDaysInMonth(4, 2015) // There were 30 days in April 2015
println(days) // Prints 30
In order to get number of days and all the dates on given month and year, try this.
func getAllDates(month: Int, year: Int) -> [Date] {
let dateComponents = DateComponents(year: year, month: month)
let calendar = Calendar.current
let date = calendar.date(from: dateComponents)!
let range = calendar.range(of: .day, in: .month, for: date)!
let numDays = range.count
let formatter = DateFormatter()
formatter.dateFormat = "yyyy MM dd"
formatter.timeZone = TimeZone(abbreviation: "GMT+0:00")
var arrDates = [Date]()
for day in 1...numDays {
let dateString = "\(year) \(month) \(day)"
if let date = formatter.date(from: dateString) {
arrDates.append(date)
}
}
return arrDates
}
Usage:
let arrDatesInGivenMonthYear = getAllDates(month: 1, year: 2018)
debugPrint(arrDatesInGivenMonthYear)
//Output: [2018-01-01 00:00:00 +0000, 2018-01-02 00:00:00 +0000, ... , 2018-01-31 00:00:00 +0000]
let numberOfDays = arrDatesInGivenMonthYear.count
debugPrint(numberOfDays)
//Output: 31
Swift 5
Another way to approach this:
extension Date {
func daysInMonth(_ monthNumber: Int? = nil, _ year: Int? = nil) -> Int {
var dateComponents = DateComponents()
dateComponents.year = year ?? Calendar.current.component(.year, from: self)
dateComponents.month = monthNumber ?? Calendar.current.component(.month, from: self)
if
let d = Calendar.current.date(from: dateComponents),
let interval = Calendar.current.dateInterval(of: .month, for: d),
let days = Calendar.current.dateComponents([.day], from: interval.start, to: interval.end).day
{ return days } else { return -1 }
}
}
here is the swift 4.0 version
func getTotalDate(){
// choose the month and year you want to look
var dateComponents = DateComponents()
dateComponents.year = 2018
dateComponents.month = 10
let calendar = Calendar.current
let datez = calendar.date(from: dateComponents)
// change .month into .year to see the days available in the year
let interval = calendar.dateInterval(of: .month, for: datez!)!
let days = calendar.dateComponents([.day], from: interval.start, to: interval.end).day!
print(days)
}
What about for a given year?
The following is printing the number of days in the date's month:
let range = userCalendar.range(of: .day, in: .year, for: Date())!
print("Days In Year: \(range.count)") // prints 31
... and not the number of days in the date's year as expected :/