Working Out The Start and End of a Day. Swift

Working out the start and end of a day. Swift

We can create a more generic function using the methods on NSCalendar:

func rangeOfPeriod(period: NSCalendarUnit, date: NSDate) -> (NSDate, NSDate) {
let calendar = NSCalendar.currentCalendar()
var startDate: NSDate? = nil

// let's ask calendar for the start of the period
calendar.rangeOfUnit(period, startDate: &startDate, interval: nil, forDate: date)

// end of this period is the start of the next period
let endDate = calendar.dateByAddingUnit(period, value: 1, toDate: startDate!, options: [])

// you can subtract 1 second if you want to make "Feb 1 00:00:00" into "Jan 31 23:59:59"
// let endDate2 = calendar.dateByAddingUnit(.Second, value: -1, toDate: endDate!, options: [])

return (startDate!, endDate!)
}

Called as

 print("\(rangeOfPeriod(.WeekOfYear, date: NSDate()))")
print("\(rangeOfPeriod(.Day, date: NSDate()))")

Putting it into your code:

public class Date {
let dateFormatter = NSDateFormatter()
let date = NSDate()
let calendar = NSCalendar.currentCalendar()

func rangeOfPeriod(period: NSCalendarUnit) -> (NSDate, NSDate) {
var startDate: NSDate? = nil

calendar.rangeOfUnit(period, startDate: &startDate, interval: nil, forDate: date)

let endDate = calendar.dateByAddingUnit(period, value: 1, toDate: startDate!, options: [])

return (startDate!, endDate!)
}

func calcStartAndEndDateForWeek() {
let (startOfWeek, endOfWeek) = rangeOfPeriod(.WeekOfYear)

print("Start of week = \(dateFormatter.stringFromDate(startOfWeek))")
print("End of the week = \(dateFormatter.stringFromDate(endOfWeek))")
}

func calcStartAndEndDateForDay() {
let (startOfDay, endOfDay) = rangeOfPeriod(.Day)

print("Start of day = \(dateFormatter.stringFromDate(startOfDay))")
print("End of the day = \(dateFormatter.stringFromDate(endOfDay))")
}

init() {
dateFormatter.dateFormat = "dd-MM-yyyy"
}
}

let myDate = Date()
myDate.calcStartAndEndDateForWeek()
myDate.calcStartAndEndDateForDay()

NSDate beginning of day and end of day

You are missing NSDayCalendarUnit in

NSDateComponents *components = [cal components:( NSMonthCalendarUnit | NSYearCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ) fromDate:date];

Neat way to get end of day for date?

A better way would be to get the start of the next day and subtract 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 second.

Do you get what I want to say? It's very hard to define the end of the day. 23:59 is certainly not the end of the day, there is almost a whole minute left until the next day. And even 23:59:59 is not the end of a day. Because there is an infinite amount of fraction seconds between this time and the start of the next day. As far as I know NSDate supports nanoseconds out of the box, so in the current implementation there are at least 1 000 000 000 possible NSDates between 23:59:59 and the next day.

That's why you should see if you can find a way to use the start of the next day.

For example, instead of if (startOfDay <= date && date <= endOfDay) you could use if (startOfDay <= date && date < startOfNextDay).

To calculate the start of the next day you have to use NSCalendar. In iOS8 Apple added a couple of nice methods to make these calculations short:

let calendar = NSCalendar.currentCalendar()
let startOfDay = calendar.startOfDayForDate(NSDate())
let startOfNextDay = calendar.dateByAddingUnit(.CalendarUnitDay, value: 1, toDate: startOfDay, options: nil)!

EDIT: Since you now state that you want to query a database you don't need to find the end of the day. Check if the date is on or after the start of the day, and before the start of the next day.

Swift - Start day and end day of the week before previous week

Something like this should work:

let cal = NSCalendar.currentCalendar()

let components = NSDateComponents()
components.weekOfYear -= 1

if let date = cal.dateByAddingComponents(components, toDate: NSDate(), options: NSCalendarOptions(0)) {
var beginningOfWeek: NSDate?
var weekDuration = NSTimeInterval()
if cal.rangeOfUnit(.CalendarUnitWeekOfYear, startDate: &beginningOfWeek, interval: &weekDuration, forDate: date) {
let endOfWeek = beginningOfWeek?.dateByAddingTimeInterval(weekDuration)
print(beginningOfWeek) // Optional(2015-02-15 05:00:00 +0000)
print(endOfWeek) // Optional(2015-02-22 05:00:00 +0000)
}
}

first and last day of the current month in swift

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

Current Week Start and End Date

I solve the problem thanks for Support

Code :- it give the current week start and end date.

 NSDate *today = [NSDate date];
NSLog(@"Today date is %@",today);
dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"yyyy-MM-dd"];// you can use your format.

//Week Start Date

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDateComponents *components = [gregorian components:NSWeekdayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:today];

int dayofweek = [[[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:today] weekday];// this will give you current day of week

[components setDay:([components day] - ((dayofweek) - 2))];// for beginning of the week.

NSDate *beginningOfWeek = [gregorian dateFromComponents:components];
NSDateFormatter *dateFormat_first = [[NSDateFormatter alloc] init];
[dateFormat_first setDateFormat:@"yyyy-MM-dd"];
dateString2Prev = [dateFormat stringFromDate:beginningOfWeek];

weekstartPrev = [[dateFormat_first dateFromString:dateString2Prev] retain];

NSLog(@"%@",weekstartPrev);

//Week End Date

NSCalendar *gregorianEnd = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDateComponents *componentsEnd = [gregorianEnd components:NSWeekdayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:today];

int Enddayofweek = [[[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:today] weekday];// this will give you current day of week

[componentsEnd setDay:([componentsEnd day]+(7-Enddayofweek)+1)];// for end day of the week

NSDate *EndOfWeek = [gregorianEnd dateFromComponents:componentsEnd];
NSDateFormatter *dateFormat_End = [[NSDateFormatter alloc] init];
[dateFormat_End setDateFormat:@"yyyy-MM-dd"];
dateEndPrev = [dateFormat stringFromDate:EndOfWeek];

weekEndPrev = [[dateFormat_End dateFromString:dateEndPrev] retain];
NSLog(@"%@",weekEndPrev);

How to get start date and end date of the current month (Swift 3)

You should write this simple code:

let dateFormatter = DateFormatter()
let date = Date()
dateFormatter.dateFormat = "dd-MM-yyyy"

For start Date:

let comp: DateComponents = Calendar.current.dateComponents([.year, .month], from: date)
let startOfMonth = Calendar.current.date(from: comp)!
print(dateFormatter.string(from: startOfMonth))

For end Date:

var comps2 = DateComponents()
comps2.month = 1
comps2.day = -1
let endOfMonth = Calendar.current.date(byAdding: comps2, to: startOfMonth)
print(dateFormatter.string(from: endOfMonth!))

How to get start and end of the week in swift?

Your code is working perfectly fine. If you would run your code in a Playground, you could see the actual Date objects rather than there String representations. Even if you don't specify a DateFormatter, under the hood, when doing print(Date()), Swift uses a DateFormatter to print Date objects and hence that value will be a relative time instead of the absolute point in time provided by the Date object.

In a Playground you can see that the actual startOfWeek is "Sep 25, 2017 at 12:00 AM", while the endOfWeek is "Oct 1, 2017 at 12:00 AM", which are the correct values for the current week.

Don't use print(Date()) for checking the correctness of Date objects, since as you can see, it will yield unexpected results due to the underlying DateFormatters used.

Swift 3 - find number of calendar days between two dates

Turns out this is much simpler to do in Swift 3:

extension Date {    

func interval(ofComponent comp: Calendar.Component, fromDate date: Date) -> Int {

let currentCalendar = Calendar.current

guard let start = currentCalendar.ordinality(of: comp, in: .era, for: date) else { return 0 }
guard let end = currentCalendar.ordinality(of: comp, in: .era, for: self) else { return 0 }

return end - start
}
}

Edit

Comparing the ordinality of the two dates should be within the same era instead of the same year, since naturally the two dates may fall in different years.

Usage

let yesterday = Date(timeInterval: -86400, since: Date())
let tomorrow = Date(timeInterval: 86400, since: Date())

let diff = tomorrow.interval(ofComponent: .day, fromDate: yesterday)
// return 2


Related Topics



Leave a reply



Submit