How to Set an Nsdate Object to Midnight

How can I set an NSDate object to midnight?

Your statement

The problem with the above method is that you can only set one unit of
time ...

is not correct. NSCalendarUnit conforms to the RawOptionSetType protocol which
inherits from BitwiseOperationsType. This means that the options can be bitwise
combined with & and |.

In Swift 2 (Xcode 7) this was changed again to be
an OptionSetType which offers a set-like interface, see
for example Error combining NSCalendarUnit with OR (pipe) in Swift 2.0.

Therefore the following compiles and works in iOS 7 and iOS 8:

let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!

// Swift 1.2:
let components = cal.components(.CalendarUnitDay | .CalendarUnitMonth | .CalendarUnitYear, fromDate: date)
// Swift 2:
let components = cal.components([.Day , .Month, .Year ], fromDate: date)

let newDate = cal.dateFromComponents(components)

(Note that I have omitted the type annotations for the variables, the Swift compiler
infers the type automatically from the expression on the right hand side of
the assignments.)

Determining the start of the given day (midnight) can also done
with the rangeOfUnit() method (iOS 7 and iOS 8):

let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
var newDate : NSDate?

// Swift 1.2:
cal.rangeOfUnit(.CalendarUnitDay, startDate: &newDate, interval: nil, forDate: date)
// Swift 2:
cal.rangeOfUnit(.Day, startDate: &newDate, interval: nil, forDate: date)

If your deployment target is iOS 8 then it is even simpler:

let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let newDate = cal.startOfDayForDate(date)

Update for Swift 3 (Xcode 8):

let date = Date()
let cal = Calendar(identifier: .gregorian)
let newDate = cal.startOfDay(for: date)

How can I get an NSDate object for today at midnight?

Try this:

NSDate *const date = NSDate.date;
NSCalendar *const calendar = NSCalendar.currentCalendar;
NSCalendarUnit const preservedComponents = (NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay);
NSDateComponents *const components = [calendar components:preservedComponents fromDate:date];
NSDate *const normalizedDate = [calendar dateFromComponents:components];

NSDate Next day after midnight

Here is the solution in Swift. The function sets the time to the first minute of the next day, using the NSDateComponents class:

public class func getTomorrow() -> NSDate {
let cal = NSCalendar.currentCalendar()
let today = NSDate()
let dateComp = cal.components([.Year, .Month, .Day, .Hour, .Minute, .Second], fromDate: today)
dateComp.day = dateComp.day + 1
dateComp.hour = 0
dateComp.minute = 1
dateComp.second = 0
return cal.dateFromComponents(dateComp)!
}

I haven't checked if it compiles, but it should be fine.
Hope it helps !

Setting an NSDate to always use midnight


let calendar = NSCalendar.currentCalendar()
let dateAtMidnight = calendar.startOfDayForDate(NSDate())

How to retrieve number of hours past midnight from an NSDate object?

You can do this with your NSCalendar.

First, get your date:

NSDate *date = [timePicker date];

Next, convert it into its date components:

NSDateComponents *components = [[NSCalendar currentCalendar] components:NSIntegerMax fromDate:date];

Now we'll reset the hours and minutes of the date components so that it's now pointing at midnight:

[components setHour:0];
[components setMinute:0];
[components setSecond:0];

Next, we'll turn it back in to a date:

NSDate *midnight = [[NSCalendar currentCalendar] dateFromComponents:components];

Finally, we'll ask for the hours between midnight and the date:

NSDateComponents *diff = [[NSCalendar currentCalendar] components:NSHourCalendarUnit fromDate:midnight toDate:date options:0];

NSInteger numberOfHoursPastMidnight = [diff hour];

Get interval to last UTC midnight from an NSDate

NSCalendar provides a method to get the start of the day (midnight) for a given date:

NSDate *rightNowUTC = [[NSDate alloc] init];
NSDate *midnight = [NSCalendar.currentCalendar startOfDayForDate: rightNowUTC];
NSTimeInterval interval = [rightNowUTC timeIntervalSinceDate: midnight];

NSDate for today at midnight

The rangeOfUnit:... method of NSCalendar is a convenient method to
compute the start of the current day and the start of tomorrow
in your local time zone:

NSDate *now = [NSDate date];
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *todaysDate;
NSDate *tomorrowsDate;
NSTimeInterval interval;
[cal rangeOfUnit:NSDayCalendarUnit startDate:&todaysDate interval:&interval forDate:now];
tomorrowsDate = [todaysDate dateByAddingTimeInterval:interval];

so that you can use it in the predicate with >= and <:

[NSPredicate predicateWithFormat:@"(date >= %@) AND (date < %@)", todaysDate, tomorrowsDate]

to fetch all objects of the current day.


Remark: Don't let the NSLog() output of NSDate objects confuse you.
NSDate represents an absolute point in time and knows nothing about time zones.
NSLog(@"%@", todaysDate) prints the date according to the GMT time zone and not in your local time zone.

To print the dates according to your time zone, use p todaysDate in the debugger console (instead of po),
or print

[todaysDate descriptionWithLocale:[NSLocale currentLocale]]

Create NSDate with a specific time

Your concern seems to be about edge cases, this suggests to me that rather than "6pm today" you are actually looking for the "next 6pm", i.e. if the time is past 6pm you want 6pm tomorrow?

Maybe the following will help, whether my guess is correct or not:

  1. Get the current date & time - NSDate
  2. Get the current calendar - NSCalendar
  3. Set the time zone of the calendar to your desired time zone
  4. Using the calendar convert the date to components - NSDateComponents - only extracting the components for year, month, day, hour & time zone. You now have the current time components in the target time zone rounded down to the nearest hour.
  5. Create an NSDate from your extracted time components using your calendar. You now have your rounded down time as an NSDate.
  6. Using your components calculate the number of hours to add to advance the time to the next 6pm.
  7. Convert the number of hours to seconds to produce an NSTimeInterval value, add that interval to your rounded down date. NSDate will take care of the edge cases of advancing the date, changing the month, etc. as needed.

HTH

How to convert decimal-based time to NSDate?


let input = 13.50

let hour = Int(input)
let minute = Int((input - Double(Int(input))) * 60)

let resultDate = NSCalendar.currentCalendar().dateBySettingHour(hour, minute: minute, second: 0, ofDate: NSDate(), options: nil)!


Related Topics



Leave a reply



Submit