How to check if an NSDate belongs to today?
I used to check it using first 10 characters from [aDate description]. [[aDate description] substringToIndex:10] returns string like "YYYY-MM-DD" so I compared the string with the string returned by [[[NSDate date] description] substringToIndex:10].
Is there more fast and/or neat way to check?
Thanks.
In macOS 10.9+ & iOS 8+, there's a method on NSCalendar/Calendar that does exactly this!
- (BOOL)isDateInToday:(NSDate *)date
So you'd simply do
Objective-C:
BOOL today = [[NSCalendar currentCalendar] isDateInToday:date];
Swift 3:
let today = Calendar.current.isDateInToday(date)
You can compare date components:
NSDateComponents *otherDay = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:aDate];
NSDateComponents *today = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:[NSDate date]];
if([today day] == [otherDay day] &&
[today month] == [otherDay month] &&
[today year] == [otherDay year] &&
[today era] == [otherDay era]) {
//do stuff
}
Edit:
I like stefan's method more, I think it makes for a cleaner and more understandable if statement:
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *components = [cal components:(NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:[NSDate date]];
NSDate *today = [cal dateFromComponents:components];
components = [cal components:(NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:aDate];
NSDate *otherDate = [cal dateFromComponents:components];
if([today isEqualToDate:otherDate]) {
//do stuff
}
Chris, I've incorporated your suggestion. I had to look up what era was, so for anyone else who doesn't know, it distinguishes between BC and AD. This is probably unnecessary for most people, but it's easy to check and adds some certainty, so I've included it. If you're going for speed, this probably isn't a good method anyway.
NOTE as with many answers on SO, after 7 years this is totally out of date. In Swift now just use .isDateInToday
This is an offshoot to your question, but if you want to print an NSDate with "Today" or "Yesterday", use the function
- (void)setDoesRelativeDateFormatting:(BOOL)b
for NSDateFormatter
I would try to get today's date normalized to midnight and the second date, normalize to midnight then compare if it is the same NSDate.
From an Apple example here's how you normalize to midnight today's date, do the same for the second date and compare:
NSCalendar * gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents * components =
[gregorian components:
(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit)
fromDate:[NSDate date]];
NSDate * today = [gregorian dateFromComponents:components];
Working Swift extension of the suggestion by Catfish_Man:
extension Date {
var isToday: Bool {
Calendar.current.isDateInToday(self)
}
}
No need to juggle with components, eras and stuff.
NSCalendar provides an method to get the beginning of a certain time unit for an existing date.
This code will get the begin of today and another date and compare that. If it evaluates to NSOrderedSame, both dates are during the same day — so today.
NSDate *today = nil;
NSDate *beginningOfOtherDate = nil;
NSDate *now = [NSDate date];
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&today interval:NULL forDate:now];
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&beginningOfOtherDate interval:NULL forDate:beginningOfOtherDate];
if([today compare:beginningOfOtherDate] == NSOrderedSame) {
//otherDate is a date in the current day
}
extension NSDate {
func isToday() -> Bool {
let cal = NSCalendar.currentCalendar()
var components = cal.components([.Era, .Year, .Month, .Day], fromDate:NSDate())
let today = cal.dateFromComponents(components)!
components = cal.components([.Era, .Year, .Month, .Day], fromDate:self)
let otherDate = cal.dateFromComponents(components)!
return today.isEqualToDate(otherDate)
}
Worked for me on Swift 2.0
Swift version of the best answer:
let cal = NSCalendar.currentCalendar()
var components = cal.components([.Era, .Year, .Month, .Day], fromDate:NSDate())
let today = cal.dateFromComponents(components)!
components = cal.components([.Era, .Year, .Month, .Day], fromDate:aDate);
let otherDate = cal.dateFromComponents(components)!
if(today.isEqualToDate(otherDate)) {
//do stuff
}
Refer to Apple's documentation entry entitled "Performing Calendar Calculations" [link].
Listing 13 on that page suggests that to determine the number of midnights between days, you use:
- (NSInteger)midnightsFromDate:(NSDate *)startDate toDate:(NSDate *)endDate
{
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
NSInteger startDay = [calendar ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSEraCalendarUnit
forDate:startDate];
NSInteger endDay = [calendar ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSEraCalendarUnit
forDate:endDate];
return endDay - startDay;
}
You may then determine if two days are the same by using that method and seeing if it returns 0 or not.
You could also check the time interval between the date you have, and the current date:
[myDate timeIntervalSinceNow]
This will give you the time interval, in seconds, between myDate and the current date/time.
Link.
Edit: Note to everyone: I'm well aware that [myDate timeIntervalSinceNow] does not unambiguously determine whether myDate is today.
I am leaving this answer as is so that if someone is looking for something similar and [myDate timeIntervalSinceNow] is useful, they may find it here.
Swift Extension based on the best answers:
extension NSDate {
func isToday() -> Bool {
let cal = NSCalendar.currentCalendar()
if cal.respondsToSelector("isDateInToday:") {
return cal.isDateInToday(self)
}
var components = cal.components((.CalendarUnitEra | .CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay), fromDate:NSDate())
let today = cal.dateFromComponents(components)!
components = cal.components((.CalendarUnitEra | .CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay), fromDate:self);
let otherDate = cal.dateFromComponents(components)!
return today.isEqualToDate(otherDate)
}
}
If you have a lot of these date comparisons, then the calls to calendar:components:fromDate start to take up a lot of time. According to some profiling I have done, they seem to be quite expensive.
Say you are trying to determine which from some array of dates, say NSArray *datesToCompare, are the same day as some given day, say NSDate *baseDate, then you can use something like the following (partly adapted from an answer above):
NSDate *baseDate = [NSDate date];
NSArray *datesToCompare = [NSArray arrayWithObjects:[NSDate date],
[NSDate dateWithTimeIntervalSinceNow:100],
[NSDate dateWithTimeIntervalSinceNow:1000],
[NSDate dateWithTimeIntervalSinceNow:-10000],
[NSDate dateWithTimeIntervalSinceNow:100000],
[NSDate dateWithTimeIntervalSinceNow:1000000],
[NSDate dateWithTimeIntervalSinceNow:50],
nil];
// determine the NSDate for midnight of the base date:
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* comps = [calendar components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit)
fromDate:baseDate];
NSDate* theMidnightHour = [calendar dateFromComponents:comps];
// set up a localized date formatter so we can see the answers are right!
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
// determine which dates in an array are on the same day as the base date:
for (NSDate *date in datesToCompare) {
NSTimeInterval interval = [date timeIntervalSinceDate:theMidnightHour];
if (interval >= 0 && interval < 60*60*24) {
NSLog(#"%# is on the same day as %#", [dateFormatter stringFromDate:date], [dateFormatter stringFromDate:baseDate]);
}
else {
NSLog(#"%# is NOT on the same day as %#", [dateFormatter stringFromDate:date], [dateFormatter stringFromDate:baseDate]);
}
}
Output:
Nov 23, 2011 1:32:00 PM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 1:33:40 PM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 1:48:40 PM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 10:45:20 AM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 24, 2011 5:18:40 PM is NOT on the same day as Nov 23, 2011 1:32:00 PM
Dec 5, 2011 3:18:40 AM is NOT on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 1:32:50 PM is on the same day as Nov 23, 2011 1:32:00 PM
There is an easier way than many of the above answers!
NSDate *date = ... // The date you wish to test
NSCalendar *calendar = [NSCalendar currentCalendar];
if([calendar isDateInToday:date]) {
//do stuff
}
This could probably be reworked as an NSDate category, but i used:
// Seconds per day (24h * 60m * 60s)
#define kSecondsPerDay 86400.0f
+ (BOOL) dateIsToday:(NSDate*)dateToCheck
{
// Split today into components
NSCalendar* gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents* comps = [gregorian components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit)
fromDate:[NSDate date]];
// Set to this morning 00:00:00
[comps setHour:0];
[comps setMinute:0];
[comps setSecond:0];
NSDate* theMidnightHour = [gregorian dateFromComponents:comps];
[gregorian release];
// Get time difference (in seconds) between date and then
NSTimeInterval diff = [dateToCheck timeIntervalSinceDate:theMidnightHour];
return ( diff>=0.0f && diff<kSecondsPerDay );
}
(However, comparing the two date strings as in the original question almost feels 'cleaner'..)
for iOS7 and earlier:
//this is now => need that for the current date
NSDate * now = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[calendar setTimeZone:[NSTimeZone systemTimeZone]];
NSDateComponents * components = [calendar components:( NSYearCalendarUnit| NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate: now];
[components setMinute:0];
[components setHour:0];
[components setSecond:0];
//this is Today's Midnight
NSDate *todaysMidnight = [calendar dateFromComponents: components];
//now timeIntervals since Midnight => in seconds
NSTimeInterval todayTimeInterval = [now timeIntervalSinceDate: todaysMidnight];
//now timeIntervals since OtherDate => in seconds
NSTimeInterval otherDateTimeInterval = [now timeIntervalSinceDate: otherDate];
if(otherDateTimeInterval > todayTimeInterval) //otherDate is not in today
{
if((otherDateTimeInterval - todayTimeInterval) <= 86400) //86400 == a day total seconds
{
#"yesterday";
}
else
{
#"earlier";
}
}
else
{
#"today";
}
now = nil;
calendar = nil;
components = nil;
todaysMidnight = nil;
NSLog("Thank you :-)");
Check our Erica Sadun's great NSDate extension. Very simple to use. Fine it here:
http://github.com/erica/NSDate-Extensions
It's already there in this post: https://stackoverflow.com/a/4052798/362310
The correct and safe solution without force-unwrapping, working on Swift 2.2 and before iOS 8:
func isToday() -> Bool {
let calendar = NSCalendar.currentCalendar()
if #available(iOS 8.0, *) {
return calendar.isDateInToday(self)
}
let todayComponents = calendar.components([.Era, .Year, .Month, .Day], fromDate:NSDate())
let dayComponents = calendar.components([.Era, .Year, .Month, .Day], fromDate:self)
guard let today = calendar.dateFromComponents(todayComponents),
day = calendar.dateFromComponents(dayComponents) else {
return false
}
return today.compare(day) == .OrderedSame
}
Here's my 2 cent answer building on the accepted answer but supporting the newer API as well. Note: I use the Gregorian calendar as most time stamps are GMT but change yours as you see fit
func isDateToday(date: NSDate) -> Bool {
let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
if calendar.respondsToSelector("isDateInToday:") {
return calendar.isDateInToday(date)
}
let dateComponents = NSCalendarUnit.CalendarUnitYear | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitDay
let today = calendar.dateFromComponents(calendar.components(dateComponents, fromDate: NSDate()))!
let dateToCompare = calendar.dateFromComponents(calendar.components(dateComponents, fromDate: date))!
return dateToCompare == today
}
My solution is calculate how much days passed since 1970 by division and compare the integer part
#define kOneDay (60*60*24)
- (BOOL)isToday {
NSInteger offset = [[NSTimeZone defaultTimeZone] secondsFromGMT];
NSInteger days =[self timeIntervalSince1970] + offset;
NSInteger currentDays = [[NSDate date] timeIntervalSince1970] + offset;
return (days / kOneDay == currentDays / kOneDay);
}
NSDate *dateOne = yourDate;
NSDate *dateTwo = [NSDate date];
switch ([dateOne compare:dateTwo])
{
case NSOrderedAscending:
NSLog(#”NSOrderedAscending”);
break;
case NSOrderedSame:
NSLog(#”NSOrderedSame”);
break;
case NSOrderedDescending:
NSLog(#”NSOrderedDescending”);
break;
}
Related
I am trying to create a catch on an iOS app to keep people from accessing things outside of a small window.
Basically, I need the action to only fire if it is between 12-1:30PM on Sundays in London (BST Time Zone). How would I check the current time, convert it to that time zone, and then see if it matches up?
I have tried the following, but it always shows it is between that range:
- (NSDate *)dateByNeutralizingDateComponentsOfDate:(NSDate *)originalDate {
NSCalendar *gregorian = [[[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
// Get the components for this date
NSDateComponents *components = [gregorian components: (NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate: originalDate];
// Set the year, month and day to some values (the values are arbitrary)
[components setYear:2000];
[components setMonth:1];
[components setDay:1];
return [gregorian dateFromComponents:components];
}
- (BOOL)isTimeOfDate:(NSDate *)targetDate betweenStartDate:(NSDate *)startDate andEndDate:(NSDate *)endDate {
if (!targetDate || !startDate || !endDate) {
return NO;
}
// Make sure all the dates have the same date component.
NSDate *newStartDate = [self dateByNeutralizingDateComponentsOfDate:startDate];
NSDate *newEndDate = [self dateByNeutralizingDateComponentsOfDate:endDate];
NSDate *newTargetDate = [self dateByNeutralizingDateComponentsOfDate:targetDate];
// Compare the target with the start and end dates
NSComparisonResult compareTargetToStart = [newTargetDate compare:newStartDate];
NSComparisonResult compareTargetToEnd = [newTargetDate compare:newEndDate];
return (compareTargetToStart == NSOrderedDescending && compareTargetToEnd == NSOrderedAscending);
}
-(void)checkDate {
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:#"EEEE HH:mm"];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithAbbreviation:#"BST"];
[dateFormatter setTimeZone:timeZone];
NSDate *openingDate = [dateFormatter dateFromString:#"Sunday 12:00"];
NSDate *closingDate = [dateFormatter dateFromString:#"Sunday 1:30"];
NSDate *targetDate = [NSDate date];
if ([self isTimeOfDate:targetDate betweenStartDate:openingDate andEndDate:closingDate]) {
NSLog(#"TARGET IS INSIDE!");
}else {
NSLog(#"TARGET IS NOT INSIDE!");
}
}
I assume you want to use the current time as observed in England, rather than BST specifically, as BST is British Summer Time. My understanding is that, during the winter, they use UTC (formerly known as GMT). Thus we should specify the time zone in a way that will select the proper offset from UTC based on the time of year.
static BOOL dateIsAcceptable(NSDate *date) {
NSCalendar *calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
calendar.timeZone = [NSTimeZone timeZoneWithName:#"Europe/London"];
NSDateComponents *components = [calendar
components:NSCalendarUnitWeekday | NSCalendarUnitHour | NSCalendarUnitMinute
fromDate:date];
if (components.weekday != 1) {
return NO;
}
double hour = components.hour + components.minute / 60.0;
return hour >= 12 && hour < 13.5;
}
I'm trying to get the first and the last date of current quarter, i'm using it:
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitQuarter | NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
components.quarter = 1;
funStartDate = [[NSCalendar currentCalendar] dateFromComponents: components];
NSLog(#"First day of quater: %#", funStartDate);
[components setQuarter:[components quarter]+1];
funEndDate = [[NSCalendar currentCalendar] dateFromComponents: components];
NSLog(#"Last day of quater: %#", [funEndDate descriptionWithLocale:[NSLocale currentLocale]]);
But in both console print I see today's date. What I'm doing wrong?
UPDATED: I've found that Apple's bug with quarter unit is still there in iOS 7.1, so avoid using this unit in your date components.
Here I got working solution for you:
first day of a quarter:
NSDate *date = <whatever>;
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
NSDate *startOfQuarter;
[currentCalendar rangeOfUnit: NSQuarterCalendarUnit
startDate: &startOfQuarter
interval: NULL
forDate: date];
NSLog(#"quarter starts at %#", startOfQuarter);
last day of a quarter:
NSDateComponents* comps = [currentCalendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay)
fromDate:date];
NSUInteger quartalNum = (comps.month - 1) / 3 + 1;
NSUInteger lastQuartalMonthNum = quartalNum * 3;
NSUInteger nextQuartalFirstMonth = lastQuartalMonthNum + 1
[comps setMonth: nextQuartalFirstMonth];
[comps setDay: 0]; // with 0 day we get last day of previous month
NSLog(#"quarter ends at %#", [currentCalendar dateFromComponents: comps]);
Swift 3.1. Quarter component still not working. Workaround:
extension Date {
public var startOfQuarter: Date {
let startOfMonth = Calendar.current.date(from: Calendar.current.dateComponents([.year, .month], from: Calendar.current.startOfDay(for: self)))!
var components = Calendar.current.dateComponents([.month, .day, .year], from: startOfMonth)
let newMonth: Int
switch components.month! {
case 1,2,3: newMonth = 1
case 4,5,6: newMonth = 4
case 7,8,9: newMonth = 7
case 10,11,12: newMonth = 10
default: newMonth = 1
}
components.month = newMonth
return Calendar.current.date(from: components)!
}
}
Usage:
Date().startOfQuarter
I need to get the weekday of the first day of the month. For example, for the current month September 2013 the first day falls on Sunday.
At first, get the first day of current month (for example):
NSDate *today = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorian components:(NSEraCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit) fromDate:today];
components.day = 1;
NSDate *firstDayOfMonth = [gregorian dateFromComponents:components];
Then use NSDateFormatter to print it as a weekday:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"EEEE"];
NSLog(#"%#", [dateFormatter stringFromDate:firstDayOfMonth]);
P.S. also take a look at Date Format Patterns
Here is the solution to getting the weekday name of the first day in the current month
NSDateComponents *weekdayComps = [[NSDateComponents alloc] init];
weekdayComps = [calendar.currentCalendar components:calendar.unitFlags fromDate:calendar.today];
weekdayComps.day = 1;
NSDateFormatter *weekDayFormatter = [[NSDateFormatter alloc]init];
[weekDayFormatter setDateFormat:#"EEEE"];
NSString *firstweekday = [weekDayFormatter stringFromDate:[calendar.currentCalendar dateFromComponents:weekdayComps]];
NSLog(#"FIRST WEEKDAY: %#", firstweekday);
For the weekday index, use this
NSDate *weekDate = [calendar.currentCalendar dateFromComponents:weekdayComps];
NSDateComponents *components = [calendar.currentCalendar components: NSWeekdayCalendarUnit fromDate: weekDate];
NSUInteger weekdayIndex = [components weekday];
NSLog(#"WEEKDAY INDEX %i", weekdayIndex);
You can also increment or decrement the month if needed.
Depending on the output you need you may use NSDateFormatter (as it was already said) or you may use NSDateComponents class. NSDateFormatter will give you a string representation, NSDateComponents will give you integer values. Method weekday may do what you want.
NSDateComponents *components = ...;
NSInteger val = [components weekday];
For Swift 4.2
First:
extension Calendar {
func startOfMonth(_ date: Date) -> Date {
return self.date(from: self.dateComponents([.year, .month], from: date))!
}
}
Second:
self.firstWeekDay = calendar.component(.weekday, from: calendar.startOfMonth(Date()))
I saw this post: iOS and finding Tomorrow.
The code provided is:
units = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents* comps = [[NSCalendar currentCalendar] components:units fromDate:[NSDate date]];
// Add one day
comps.day = comps.day+1; // no worries: even if it is the end of the month it will wrap to the next month, see doc
// Recompose a new date, without any time information (so this will be at midnight)
NSDate* tomorrowMidnight = [[NSCalendar currentCalendar] dateFromComponents:comps];
Problem: I need to add a day to my current date so that for example, the difference between 21st Jun 2013 and 21st May 2013 is 1 month instead of 0 month.
The code I am using:
NSDate *selectedDate = [picker2 date];
unsigned int unitFlags = NSHourCalendarUnit | NSMinuteCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit;
NSDateComponents *conversionInfo = [currCalendar components:unitFlags fromDate:selectedDate toDate:[NSDate date] options:0];
DLog(#"%i",conversionInfo.month);
DLog(#"%i",conversionInfo.day);
conversionInfo.day +=1;
DLog(#"%i",conversionInfo.day);
DLog(#"%i",conversionInfo.month);
int months = [conversionInfo month];
But when I tried to get the difference between 21st Jun 2013 and 21st May 2013 -> still returns me 0 month instead of 1 month.
Need some help on this.
Form a date component with number of days you want to add to your original date. From the current calendar form the date by adding the this component to your original date.
NSDateComponents *dateComponents = [NSDateComponents new];
dateComponents.day = 1;
NSDate *newDate = [[NSCalendar currentCalendar]dateByAddingComponents:dateComponents
toDate: selectedDate
options:0];
Here is a method I use:
+ (NSDate *)addDays:(NSInteger)days toDate:(NSDate *)originalDate {
NSDateComponents *components= [[NSDateComponents alloc] init];
[components setDay:days];
NSCalendar *calendar = [NSCalendar currentCalendar];
return [calendar dateByAddingComponents:components toDate:originalDate options:0];
}
With it, you can add as many days as you want. It also works with negative numbers, so you can subtract days.
Simple and straight forward solution :
NSDate *currentDate = [NSDate date];
NSDate *nextDate = [currentDate dateByAddingTimeInterval:(24*3600)];
This is working fine for me.
For swift googlers:
NSCalendar.currentCalendar().dateByAddingUnit(NSCalendarUnit.CalendarUnitDay, value: 1, toDate: date, options: nil)!
First Thing,you are assigning day instead of month to NSDateComponent.
Execute following code and find difference between inDate And newDate
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:NSCalendarUnitMonth fromDate:inDate];
NSInteger monthFlag = 1;
components.month = minuteFlag;
// Retrieve date with increased days count
NSDate *newDate = [[NSCalendar currentCalendar]
dateByAddingComponents:components
toDate:monthFlag
options:0];
To add any number of any components to the date, for example: 2 days or 2 months, 1 year, do the following:
Calendar.current.date(byAdding: DateComponents(month: -1), to: date)! //this create date with previous month for date.
you can initialize DateComponents with anything:
public init(calendar: Calendar? = default, timeZone: TimeZone? = default, era: Int? = default, year: Int? = default, month: Int? = default, day: Int? = default, hour: Int? = default, minute: Int? = default, second: Int? = default, nanosecond: Int? = default, weekday: Int? = default, weekdayOrdinal: Int? = default, quarter: Int? = default, weekOfMonth: Int? = default, weekOfYear: Int? = default, yearForWeekOfYear: Int? = default)
I'm struggling to figure out how to dynamically create a date object for the most previous sunday at 12:00 AM
I was thinking I could get today's date and then subtract the current day of the week + 1 at which point I could just subtract the time of the day do get down to 12AM.
so far I have the current day of the week:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps = [gregorian components:NSWeekdayCalendarUnit fromDate:[NSDate date]];
int weekday = [comps weekday];
at which point I can get today's date and subtract the difference of weekday * seconds in a day. However, how can I get today's time in seconds ??
No need to manually calculate seconds (which is dangerous anyway because of daylight saving etc.). The following should do exactly what you want:
NSDate *today = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[calendar setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en-US"]]; // force US locale, because other countries (e.g. the rest of the world) might use different weekday numbering
NSDateComponents *nowComponents = [calendar components:NSYearCalendarUnit | NSWeekCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:today];
[nowComponents setWeekday:1]; //Sunday
[nowComponents setHour:0]; // 12:00 AM = midnight (12:00 PM would be 12)
[nowComponents setMinute:0];
[nowComponents setSecond:0];
NSDate *previousSunday = [calendar dateFromComponents:nowComponents];
I'll leave worrying about transitions between daylight savings time to you:
NSCalendar *gregorian = [[NSCalendar alloc]initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [NSDate date];
NSLog(#"date %#", date);
NSDateComponents *componentsToday = [gregorian components:NSWeekdayCalendarUnit fromDate:date]; // NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit |
NSInteger days = componentsToday.weekday - 1;
NSLog(#"Days=%d", days);
NSDate *lastSunday = [date dateByAddingTimeInterval:-days*60*60*24];
NSLog(#"lastSunday %#", lastSunday);
NSDateComponents *componentsSunday = [gregorian components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:lastSunday];
[componentsSunday setHour:0];
[componentsSunday setMinute:0];
[componentsSunday setSecond:0];
NSDate *targetDate = [gregorian dateFromComponents:componentsSunday];
NSLog(#"TargetDate %#", targetDate);
#AndreasLey solution in Swift 2.0:
func getLastSunday() -> NSDate?
{
let today = NSDate();
let calendar : NSCalendar! = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
calendar.locale = NSLocale(localeIdentifier: "en-US") // force US locale, because other countries (e.g. the rest of the world) might use different weekday numbering
let flags : NSCalendarUnit = [.Year , .Month, .Weekday, .WeekOfMonth, .Minute , .Second]
let nowComponents = calendar.components(flags, fromDate: today)
nowComponents.weekday = 1 //Sunday
nowComponents.hour = 0 // 12:00 AM = midnight (12:00 PM would be 12)
nowComponents.minute = 0
nowComponents.second = 0;
let previousSunday = calendar.dateFromComponents(nowComponents);
return previousSunday
}
This code is setting 12:00 am in your selected date from UIDatePicker.
NSDate *oldDateSelected = datePicker.date;
unsigned unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *comps = [calendar components:unitFlags fromDate:oldDateSelected];
comps.hour = 00;
comps.minute = 00;
comps.second = 44;
NSDate *newDate = [calendar dateFromComponents:comps];
return newDate;