I hope you can help me with this:
I´m writing a App that should show if a shop has actually open.
For this i declared for each day and each opening times different variables / NSDate-Objects like (setting the dateformatter I´ve done before):
NSDate *mondayMorningOpening = [dateFormatter dateFromString:#"08:00"];
NSDate *montagMorningClosing = [dateFormatter dateFromString:#"12:30"];
NSDate *mondayNoonOpening = [dateFormatter dateFromString:#"15:00"];
NSDate *montagNoonClosing = [dateFormatter dateFromString:#"21:30"];
I´ve also set a NSDate for the actual time:
NSString *tempDate1 = [dateFormatter stringFromDate:date];
NSDate *actualTime = [dateFormatter dateFromString:tempDate1];
Now I want to calculate if the actual time is before or after the time range for the opening times of the shop. I´ve done this:
if ([actualTime earlierDate: mondayMorningClosing && [aktuelleZeit laterDate: mondayMorningOpening])
{
NSLog (#"The shop is open!");
}
else if ([actualTime earlierDate: mondayNoonClosing]&& [actualTime laterDate: mondayNoonOpening])
{
NSLog (#"The shop is open!");
}
else
{
NSLog (#"The shop is closed!");
}
But no matter what time it is, it´s always shown "The shop is open!".
Maybe you have an idea what to do that i can show the opening status right...
You misunderstood the meaning of earlierDate and laterDate.The methods are not "isEarlierDate" and "isLaterDate", they do not return a BOOL.These methods return a NSDate object, the earlier (or later) of the two dates.They're not nil objects, so they're always evaluated to true.
Compare the two dates taking it's time interval:
if ([actualTime timeIntervalSinceDate: mondayMorningClosing]<0 && [aktuelleZeit timeIntervalSinceDate: mondayMorningOpening]>0)
{
NSLog (#"The shop is open!");
}
You can compare two dates, but as a result you will have a NSDate:
if ([date1 compare:date2] == NSOrderedDescending) {
NSLog(#"date1 is later than date2");
} else if ([date1 compare:date2] == NSOrderedAscending) {
NSLog(#"date1 is earlier than date2");
}
If you have 2 dates you can determine if an NSDate is between those two like this:
- (BOOL)isDate:(NSDate *)date betweenFirstDate:(NSDate *)firstDate andSecondDate:(NSDate *)secondDate
{
BOOL isEqualToFirstOrSecond = [date compare:firstDate] == NSOrderedSame || [date compare:secondDate] == NSOrderedSame;
BOOL isBetweenFirstAndSecond = [date compare:firstDate] == NSOrderedDescending && [date compare:secondDate] == NSOrderedAscending;
return isEqualToFirstOrSecond || isBetweenFirstAndSecond;
}
Related
In Objective-C, how to test if today is not after a specific date?
I am using the following way but am curious if there is a better way or other alternatives to go about this.
NSString *dateString = #"20140928";
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyyMMdd"];
NSDate *expirationDate = [dateFormat dateFromString:dateString];
NSDate *today = [NSDate date];
if ([today laterDate:expirationDate] != today) {
NSLog(#"Today is not after expirationDate");
}
Most of your code is getting the expiration date so that doesn't really count.
Once you have the date then using laterDate: or compare: with [NSDate date] are two simple ways.
You could also do:
if ([expirationDate timeIntervalSinceNow] > 0) {
// expiration date is after "now"
}
This avoids the need to use [NSDate date].
As an alternative there is:
if ([today compare:expirationDate] == NSOrderedAscending)
// expirationDate comes "after" today
if ([today compare:expirationDate] == NSOrderedDescending)
// expirationDate comes "before" today
if ([today compare:expirationDate] == NSOrderedSame)
// expirationDate equals today
I want to compare different times of outlets with ipad current time so what i did was this
if(CT!=nil && startTime!=nil &&endTime!=nil)
{
/* If current time is greater than begin time but less than end time then he can give feedack
*/
if (([CT compare:startTime]== NSOrderedDescending) && ([CT compare:endTime]== NSOrderedAscending) ) {
return YES;
}
else if (([CT compare:startTime]== NSOrderedSame) || ([CT compare:endTime]== NSOrderedSame))
{
return YES;
}
else if (([CT compare:startTime]== NSOrderedDescending) && ([CT compare:endTime]== NSOrderedDescending))
{
return NO; // out of outlet timings
}
This seems to be working good till now but when i change the outlet time to
start time = 18:30PM
end time = 2:00 AM
Then in that case the above code fails, when the ipad clocks at 1:00AM then the first if condition fails so i added this code below
if (([CT compare:startTime]== NSOrderedAscending) && ([CT compare:endTime]== NSOrderedAscending))
{
}
Now as a developer i am sure that if the device clocks at 1:00 AM then it wont fail but what if somebody updated the outlet timing to
start time = 9:00AM
end time = 11:00 AM
and current device time = 8:00 AM
then in the above case my the second code will fail.
what i want is some suggestion as in what i can do in the second if condition
Code that creates CT is :
NSDate *sysDate = [NSDate date];
NSDateFormatter *df = [[NSDateFormatter alloc]init];
[df setDateFormat:#"HH:mm:ss"];
NSString *timeString = [df stringFromDate:sysDate];
NSDate *CT = [df dateFromString:timeString];
startTime and endTime are date objects stored in the plist.
Rewrite your conditions as if there were numbers instead of dates and see what they actually do (NSOrderedDescending becomes > "greater than", NSOrderedAscending becomes < "less than"):
if (ctNumber > startNumber && ctNumber < endNumber)
{ ... }
else if (ctNumber == startNumber || ctNumber == endNumber)
{ ... }
else if (ctNumber > startNumber && ctNumber > endNumber)
{ ... }
I hope this way it's obvious the last one is not what you mean at all, and the other condition you tried later was still incorrect. The correct one is (ctNumber < startNumber || ctNumber > endNumber) which is exactly what standalone else would do, so you can just drop it:
if (ctNumber > startNumber && ctNumber < endNumber)
{ ... }
else if (ctNumber == startNumber || ctNumber == endNumber)
{ ... }
else
{ /* otherwise ; everything else ; in all other cases */ ... }
But you really should follow #ILYA2606 advice and compare time intervals (which are numbers) in future to avoid further confusions like this. It will also allow you to use <= and >= and so drop the middle condition:
NSTimeInterval ctNumber = [CT timeIntervalSince1970];
NSTimeInterval startNumber = [startDate timeIntervalSince1970];
NSTimeInterval endNumber = [endDate timeIntervalSince1970];
BOOL ctLiesInsideInterval = (ctNumber >= startNumber && ctNumber <= endNumber);
return ctLiesInsideInterval;
And finally, I have to point out that the date formatter code that creates CT is nonsense and is equivalent to simply using current time:
NSDate* CT = [NSDate date];
Convert NSString to NSDate, compare timeIntervals:
NSDateFormatter *df = [[NSDateFormatter alloc]init];
[df setDateFormat:#"HH:mm:ss"];
NSDate *CTDate = [df dateFromString:CT];
NSDate *startDate = [df dateFromString:startTime];
NSTimeInterval CTInterval = [CTDate timeIntervalSince1970];
NSTimeInterval startInterval = [startDate timeIntervalSince1970];
NSTimeInterval deltaInterval = startInterval - CTInterval;
if(deltaInterval < 0){
//Ascending (CT < startTime)
}
else if(deltaInterval > 0){
//Descending (CT > startTime)
}
else{
//Some (CT = startTime)
}
Try this one..
NSDate *currentDate=[NSDate date];
NSTimeInterval daysInSeconds = 60*60;
NSDate *starttime= [currentDate dateByAddingTimeInterval:daysInSeconds];
daysInSeconds = 2*60*60;
NSDate *endtime= [currentDate dateByAddingTimeInterval:daysInSeconds];
if( [starttime compare:currentDate]==NSOrderedAscending ){
//Ascending (CT < startTime)
}
if( [starttime compare:currentDate]==NSOrderedDescending ){
//Descending (CT > startTime)
}
if( [endtime compare:currentDate]==NSOrderedAscending ){
//Ascending (CT < endtime)
}
if( [endtime compare:currentDate]==NSOrderedDescending ){
//Descending (CT > endtime)
}
Good afternoon,
How do you check if a date is between two dates? I know I have to convert the data strings to NSDate values first:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MM/dd/yyyy"];
NSDate *date1 = [dateFormatter dateFromString:#"01/01/2001"];
NSDate *date2 = [dateFormatter dateFromString:#"01/01/2010"];
NSDate *userDate = [dateFormatter dateFromString:#"12/12/2001"];
And then I have to use an if-statement, but I am not quite sure how to go about it. Here is what I need:
if (userDate is between date1 and date2)
{
}
Any help with the if-statement would be appreciated. Thank you!
Use NSDate -compare::
if (([date1 compare:userDate] == NSOrderedAscending) && ([date2 compare:userDate] == NSOrderedDescending)) {
// Do something
}
of the top of my head so check the syntax ;-)
if (([userDate laterDate: date1] == userDate) && ([userDate laterDate: date2] == date2)){
}
if(([userDate compare: date1] == NSOrderedDescending) && ([userDate compare: date2] == NSOrderedAscending)){
//do something
}
I need to take a stored NSDate and reliably determine whether it falls within the current moment's hour, day or week. I seem to have hacked together a solution, but not having solved this problem before, am not entirely confident that it's a reliable one.
Will this survive user-set 12 vs 24 hour time? the date formatting guide indicates that this user setting can lead to some unanticipated date behavior: "In iOS, the user can override the default AM/PM versus 24-hour time setting. This may cause NSDateFormatter to rewrite the format string you set."
What about the basic code pattern for this problem? Does this code seem to reliably serve its purpose? I hate to post a "check my code" sort of question, but it's an unfamiliar-enough problem to me, and tricky enough to rigorously test, that it seemed justified. NSDateFormatter is also relatively new to me; another motivation for the question.
NOTE: The main source of my nervousness is that converting dates to strings and then doing a string compare seems an inherently fragile method of solving this problem. But it's the best I could come up with.
Quick reference: the dateFormats I used for each of the three cases were:
dateFormat = #"yyyyMMddHH"; // For "this hour" check
dateFormat = #"yyyyMMdd"; // For "today" check
dateFormat = #"yyyyww"; // For "this week" check
Thanks! Code Follows:
- (BOOL)didThisCycle {
// Case 1: hourly; Case 2: daily; Case 3: weekly
BOOL did = NO;
NSDate *now = [NSDate date];
NSDate *lastDid = [self.didDates lastObject];
if (![lastDid isKindOfClass:[NSDate class]]) { // Crash protection
return NO;
}
int type = [self.goalType intValue];
switch (type) {
case 1:
{
// If hourly check hour
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
formatter.dateFormat = #"yyyyMMddHH";
NSString *nowString = [formatter stringFromDate:now];
NSString *lastDidString = [formatter stringFromDate:lastDid];
if ([nowString isEqualToString:lastDidString]) {
did = YES;
} else {
did = NO;
}
break;
}
case 2:
{
// If daily check day
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
formatter.dateFormat = #"yyyyMMdd";
NSString *nowString = [formatter stringFromDate:now];
NSString *lastDidString = [formatter stringFromDate:lastDid];
if ([nowString isEqualToString:lastDidString]) {
did = YES;
} else {
did = NO;
}
break;
}
case 3:
{
// If weekly check week
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
formatter.dateFormat = #"yyyyww";
NSString *nowString = [formatter stringFromDate:now];
NSString *lastDidString = [formatter stringFromDate:lastDid];
if ([nowString isEqualToString:lastDidString]) {
did = YES;
} else {
did = NO;
}
break;
}
default:
{
did = NO;
break;
}
}
return did;
}
Use the NSDateComponents class, like so:
NSDate *someDate = // whatever
NSDate *now = [NSDate date];
NSDateComponents *thenComponents = [[NSCalendar currentCalendar] components:NSHourCalendarUnit|NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:someDate];
NSDateComponents *nowComponents = [[NSCalendar currentCalendar] components:NSHourCalendarUnit|NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:now];
if([thenComponents year] == [nowComponents year] && [thenComponents month] == [nowComponents month] && [thenComponents day] == [nowComponents day] && [thenComponents hour] == [nowComponents hour])
{
// hooray
}
Remove the “hour” component if you just want to check the day, or remove both that and “day” (and replace with NSWeekCalendarUnit and the -week method) to check the week.
I have a NSDate that I must compare with other two NSDate and I try with NSOrderAscending and NSOrderDescending but if my date is equal at other two dates?
Example: if I have a myDate = 24/05/2011 and other two that are one = 24/05/2011 and two 24/05/2011 what can I use?
According to Apple documentation of NSDate compare:
Returns an NSComparisonResult value that indicates the temporal ordering of the receiver and another given date.
- (NSComparisonResult)compare:(NSDate *)anotherDate
Parameters anotherDate
The date with which to compare the
receiver. This value must not be nil.
If the value is nil, the behavior is
undefined and may change in future
versions of Mac OS X.
Return Value
If:
The receiver and anotherDate are
exactly equal to each other,
NSOrderedSame
The receiver is later in
time than anotherDate,
NSOrderedDescending
The receiver is
earlier in time than anotherDate,
NSOrderedAscending
In other words:
if ([date1 compare:date2] == NSOrderedSame) ...
Note that it might be easier in your particular case to read and write this :
if ([date2 isEqualToDate:date2]) ...
See Apple Documentation about this one.
After searching, I've got to conclusion that the best way of doing it is like this:
- (BOOL)isEndDateIsSmallerThanCurrent:(NSDate *)checkEndDate
{
NSDate* enddate = checkEndDate;
NSDate* currentdate = [NSDate date];
NSTimeInterval distanceBetweenDates = [enddate timeIntervalSinceDate:currentdate];
double secondsInMinute = 60;
NSInteger secondsBetweenDates = distanceBetweenDates / secondsInMinute;
if (secondsBetweenDates == 0)
return YES;
else if (secondsBetweenDates < 0)
return YES;
else
return NO;
}
You can change it to difference between hours also.
If you want to compare date with format of dd/MM/yyyy only, you need to add below lines between NSDate* currentdate = [NSDate date]; && NSTimeInterval distance
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd/MM/yyyy"];
[dateFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:#"en_US"]
autorelease]];
NSString *stringDate = [dateFormatter stringFromDate:[NSDate date]];
currentdate = [dateFormatter dateFromString:stringDate];
I take it you are asking what the return value is in the comparison function.
If the dates are equal then returning NSOrderedSame
If ascending ( 2nd arg > 1st arg ) return NSOrderedAscending
If descending ( 2nd arg < 1st arg ) return NSOrderedDescending
I don't know exactly if you have asked this but if you only want to compare the date component of a NSDate you have to use NSCalendar and NSDateComponents to remove the time component.
Something like this should work as a category for NSDate:
- (NSComparisonResult)compareDateOnly:(NSDate *)otherDate {
NSUInteger dateFlags = NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit;
NSCalendar *gregorianCalendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents *selfComponents = [gregorianCalendar components:dateFlags fromDate:self];
NSDate *selfDateOnly = [gregorianCalendar dateFromComponents:selfComponents];
NSDateComponents *otherCompents = [gregorianCalendar components:dateFlags fromDate:otherDate];
NSDate *otherDateOnly = [gregorianCalendar dateFromComponents:otherCompents];
return [selfDateOnly compare:otherDateOnly];
}
NSDate actually represents a time interval in seconds since a reference date (1st Jan 2000 UTC I think). Internally, a double precision floating point number is used so two arbitrary dates are highly unlikely to compare equal even if they are on the same day. If you want to see if a particular date falls on a particular day, you probably need to use NSDateComponents. e.g.
NSDateComponents* dateComponents = [[NSDateComponents alloc] init];
[dateComponents setYear: 2011];
[dateComponents setMonth: 5];
[dateComponents setDay: 24];
/*
* Construct two dates that bracket the day you are checking.
* Use the user's current calendar. I think this takes care of things like daylight saving time.
*/
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDate* startOfDate = [calendar dateFromComponents: dateComponents];
NSDateComponents* oneDay = [[NSDateComponents alloc] init];
[oneDay setDay: 1];
NSDate* endOfDate = [calendar dateByAddingComponents: oneDay toDate: startOfDate options: 0];
/*
* Compare the date with the start of the day and the end of the day.
*/
NSComparisonResult startCompare = [startOfDate compare: myDate];
NSComparisonResult endCompare = [endOfDate compare: myDate];
if (startCompare != NSOrderedDescending && endCompare == NSOrderedDescending)
{
// we are on the right date
}
Check the following Function for date comparison first of all create two NSDate objects and pass to the function:
Add the bellow lines of code in viewDidload or according to your scenario.
-(void)testDateComaparFunc{
NSString *getTokon_Time1 = #"2016-05-31 03:19:05 +0000";
NSString *getTokon_Time2 = #"2016-05-31 03:18:05 +0000";
NSDateFormatter *dateFormatter=[NSDateFormatter new];
[dateFormatter setDateFormat:#"yyyy-MM-dd hh:mm:ss Z"];
NSDate *tokonExpireDate1=[dateFormatter dateFromString:getTokon_Time1];
NSDate *tokonExpireDate2=[dateFormatter dateFromString:getTokon_Time2];
BOOL isTokonValid = [self dateComparision:tokonExpireDate1 andDate2:tokonExpireDate2];}
here is the function
-(BOOL)dateComparision:(NSDate*)date1 andDate2:(NSDate*)date2{
BOOL isTokonValid;
if ([date1 compare:date2] == NSOrderedDescending) {
//"date1 is later than date2
isTokonValid = YES;
} else if ([date1 compare:date2] == NSOrderedAscending) {
//date1 is earlier than date2
isTokonValid = NO;
} else {
//dates are the same
isTokonValid = NO;
}
return isTokonValid;}
Simply change the date and test above function :)