Know if a date(weekday) is bettween two other dates(weekedaysº) - objective-c

Im trying to know if the current day of the week + and hour is in between of 2 other weekday + hour.
Let's say, right now is "Tuesday 16:26" and there is an interval that starts with "Tuesday 16:00" and "Tuesday 22:00" so it should return YES.
Im creating dates from the previous strings, and this function tells me if it's in the interval.
This function is part of a class, whose attributes "fechaInicio" and "fechaFin" are start date and end adate respectively.
- (BOOL)dateInInterval:(NSDate *)testDate {
// date1 is the instance variable containing the starting date
// date2 is the instance variable containing the ending date
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:#"en"] autorelease]];
[dateFormatter setDateFormat:#"EEEE HH:mm"];
NSString *dateString = [dateFormatter stringFromDate:self.fechaInicio];
NSLog(#"La fecha es: %#", dateString);
dateString = [dateFormatter stringFromDate:self.fechaFin];
NSLog(#"La fecha es: %#", dateString);
NSLog(#"time interval nicio: %d", [testDate timeIntervalSinceDate:self.fechaInicio]);
NSLog(#"time interval fin: %d", [testDate timeIntervalSinceDate:self.fechaFin]);
return ([testDate timeIntervalSinceDate:self.fechaInicio] > 0 &&
[testDate timeIntervalSinceDate:self.fechaFin] < 0);
}
The thing is that in never returns YES, even though I can see the date is in the interval. Im afraid how Im turning the string to date. I input "Tuesday 16:00" what year is it, what month, if I format the actual date to "EEEE HH" will it save the month and year?
Thanks

For your case, I'd advice to find some fixed known date for Monday and apply the full date for each EEEE HH:mm string. This will give correct values inside date and i think your logic will start working

Related

NSDateFormatter doesRelativeDateFormatting returns unexpected relative day value

Using NSDateFormatter on macOS 10.13.3, I'm getting incorrect values when using doesRelativeDateFormatting set to YES. I've seen that there may be an issue with relative dates when using a custom format on the formatter but I am using standard dateStyle & timeStyle settings.
As an example, comparing the current date in New York City to the date in Sydney, Australia using appropriately configured date formatters without using doesRelativeDateFormatting, the string output from the date formatters correctly shows the day in Sydney being +1 from the day in NYC. When I enable doesRelativeDateFormatting on the same formatters, the relative date for Sydney returns incorrectly as same day ('Today'). Code that demonstrates these results:
int main(int argc, char *argv[]) {
#autoreleasepool {
NSDate *now = [NSDate date];
NSDateFormatter *localDateFormatter = [NSDateFormatter new];
localDateFormatter.timeZone = [NSTimeZone timeZoneWithName:#"America/New_York"];
localDateFormatter.dateStyle = NSDateFormatterFullStyle;
localDateFormatter.timeStyle = NSDateFormatterFullStyle;
NSDateFormatter *remoteDateFormatter = [NSDateFormatter new];
remoteDateFormatter.timeZone = [NSTimeZone timeZoneWithName:#"Australia/Sydney"];
remoteDateFormatter.dateStyle = NSDateFormatterFullStyle;
remoteDateFormatter.timeStyle = NSDateFormatterFullStyle;
NSLog(#" Now in NYC: %#", [localDateFormatter stringFromDate:now]);
NSLog(#" Now in Sydney: %#", [remoteDateFormatter stringFromDate:now]);
localDateFormatter.doesRelativeDateFormatting = YES;
remoteDateFormatter.doesRelativeDateFormatting = YES;
NSLog(#" Relative now in NYC: %#", [localDateFormatter stringFromDate:now]);
NSLog(#"Relative now in Sydney: %#", [remoteDateFormatter stringFromDate:now]);
}
}
Output:
2018-01-26 14:42:28.478 Untitled[40694:1821879] Now in NYC: Friday, January 26, 2018 at 2:42:28 PM Eastern Standard Time
2018-01-26 14:42:28.479 Untitled[40694:1821879] Now in Sydney: Saturday, January 27, 2018 at 6:42:28 AM Australian Eastern Daylight Time
2018-01-26 14:42:28.479 Untitled[40694:1821879] Relative now in NYC: Today at 2:42:28 PM Eastern Standard Time
2018-01-26 14:42:28.479 Untitled[40694:1821879] Relative now in Sydney: Today at 6:42:28 AM Australian Eastern Daylight Time
Is this a bug in NSDateFormatter or am I doing something wrong in my configuration of the formatter? Thanks.
Your output is correct. Call anyone on the phone anywhere in the world and ask them what the date is and they will all say "today". Just because it's a different day of the week in two parts of the world doesn't mean it isn't "today" locally everywhere.
You are letting yourself get confused by comparing the output of two different timezones that happen to be in two different days when the code is run.
The idea of "relative" date formatting is that the output is a string relative to "now" in the given timezone. It's not relative to any other timezone. Whichever one is set on the date formatter.
Of course, #rmaddy is correct. Enabling doesRelativeDateFormatting and then comparing the date to its own timezone will report 'Today', as it should.
So, the key is to get the date in the remote timezone then use that date relative to the preferred (local) timezone and using the local date formatter's relative date string. Modifying my code to account for the time difference between the two timezones, I calculate the local date offset by the delta and use the local date formatter to get the date string (still using the remote date formatter for the time string because it includes the timezone name).
This isn't perfect because I'm not properly localizing the string (' at ' is being manually inserted without localization) but this modified code basically gets the results for which I'm looking:
int main(int argc, char *argv[]) {
#autoreleasepool {
NSDate *now = [NSDate date];
NSDateFormatter *localDateFormatter = [NSDateFormatter new];
localDateFormatter.timeZone = [NSTimeZone timeZoneWithName:#"America/New_York"];
localDateFormatter.dateStyle = NSDateFormatterFullStyle;
localDateFormatter.timeStyle = NSDateFormatterFullStyle;
NSDateFormatter *remoteDateFormatter = [NSDateFormatter new];
remoteDateFormatter.timeZone = [NSTimeZone timeZoneWithName:#"Australia/Sydney"];
remoteDateFormatter.dateStyle = NSDateFormatterFullStyle;
remoteDateFormatter.timeStyle = NSDateFormatterFullStyle;
NSLog(#" Now in NYC: %#", [localDateFormatter stringFromDate:now]);
NSLog(#" Now in Sydney: %#", [remoteDateFormatter stringFromDate:now]);
localDateFormatter.doesRelativeDateFormatting = YES;
NSLog(#" Relative now in NYC: %#", [localDateFormatter stringFromDate:now]);
NSInteger localSecondsFromGMT = [localDateFormatter.timeZone secondsFromGMTForDate:now];
NSInteger remoteSecondsFromGMT = [remoteDateFormatter.timeZone secondsFromGMTForDate:now];
NSInteger remoteTimeZoneDelta = (remoteSecondsFromGMT - localSecondsFromGMT);
NSDate *remoteDate = [now dateByAddingTimeInterval:(NSTimeInterval)remoteTimeZoneDelta];
localDateFormatter.timeStyle = NSDateFormatterNoStyle;
remoteDateFormatter.dateStyle = NSDateFormatterNoStyle;
NSString *remoteRelativeDate = [localDateFormatter stringFromDate:remoteDate];
NSString *remoteRelativeTime = [remoteDateFormatter stringFromDate:now];
NSLog(#"Relative now in Sydney: %# at %#", remoteRelativeDate, remoteRelativeTime);
}
}
Output:
2018-01-27 16:08:12.856 Untitled[95771:3146343] Now in NYC: Saturday, January 27, 2018 at 4:08:12 PM Eastern Standard Time
2018-01-27 16:08:12.857 Untitled[95771:3146343] Now in Sydney: Sunday, January 28, 2018 at 8:08:12 AM Australian Eastern Daylight Time
2018-01-27 16:08:12.857 Untitled[95771:3146343] Relative now in NYC: Today at 4:08:12 PM Eastern Standard Time
2018-01-27 16:08:12.857 Untitled[95771:3146343] Relative now in Sydney: Tomorrow at 8:08:12 AM Australian Eastern Daylight Time
This is somewhat inelegant but it works for my current needs.

showing a null value in NSdateformatter

From the the log start time value is printed. why end time showing (null) value.
NSString *start=#"00:01:00";
NSString *end=#"24:00:00";
NSDateFormatter *formatter1 = [[NSDateFormatter alloc] init];
[formatter1 setDateFormat:#"HH:mm:ss"];
NSDate *end1=[[NSDate alloc]init];
end1=[formatter1 dateFromString:end];
NSLog(#"end1:%#",end1);
**Log print - end1:(null)**NSDate *start1=[[NSDate alloc]init];start1=[formatter1 dateFromString:start];NSLog(#"start1:%#",start1);**Log print - start1:1999-12-31 18:31:00 +0000**
The hour value must be within 0 and 23, so 24 is an invalid hour value even for a 24hour date formatter. See http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns for valid values and formatters.
Since 24 as hour is invalid, the formatter returns nil . In your case you would need to add the date to achieve start 00:01:00 and end 00:00:00 which is the beginning of the next day.
Use
NSString *end = #"00:00:00";
instead of
NSString *end = #"24:00:00";

How to get the day of week from a given number

I want to have the day of week name for a given number, here is the pseudo-code :
getDayStringForInt:0 = sunday
getDayStringForInt:1 = monday
getDayStringForInt:2 = tuesday
getDayStringForInt:3 = wenesday
getDayStringForInt:4 = thursday
getDayStringForInt:5 = friday
getDayStringForInt:6 = saturday
I have tried with the follow code, but some thing is not working ...
- (void) setPeriodicityDayOfWeek:(NSNumber *)dayOfWeek{
gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
dateFormatter = [[NSDateFormatter alloc] init];
NSLocale *frLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
[dateFormatter setLocale:frLocale];
[gregorian setLocale:frLocale];
NSDate *today = [NSDate date];
NSDateComponents *nowComponents = [gregorian components:NSYearCalendarUnit | NSWeekCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:today];
[nowComponents setWeekday:dayOfWeek];
NSDate *alertDate = [gregorian dateFromComponents:nowComponents];
[dateFormatter setDateFormat:#"EEEE"];
NSLog(#"Day Of Week : %# - Periodicity : %#", dayOfWeek, [dateFormatter stringFromDate:alertDate]);
alert.periodicity = [dateFormatter stringFromDate:alertDate];
}
My log is very strange :
Day Of Week : 0 - Periodicity : monday
Day Of Week : 1 - Periodicity : wenesday
Day Of Week : 2 - Periodicity : friday
Day Of Week : 3 - Periodicity : friday
Day Of Week : 4 - Periodicity : tuesday
Day Of Week : 5 - Periodicity : sunday
Day Of Week : 6 - Periodicity : sunday
Any idea ? any better solution ...
Since this has become the accepted answer, I'll post the "right" solution here too. Credits to Rob's answer.
The whole thing can simply be achieved using the [shortWeekdaySymbols][1] method of NSDateFormatter, so the full solution boils down to
- (NSString *)stringFromWeekday:(NSInteger)weekday {
NSDateFormatter * dateFormatter = [NSDateFormatter new];
dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
return dateFormatter.shortWeekdaySymbols[weekday];
}
Original answer
Beware, you're passing a pointer to NSNumber to a method that requires a NSInteger.
The compiler is not warning you since a pointer is indeed an integer, just not the one you would expect.
Consider this simple test:
- (void)foo:(NSInteger)a {
NSLog(#"%i", a);
}
- (void)yourMethod {
[self foo:#1]; // #1 is the boxed expression for [NSNumber numberWithInt:1]
}
This prints something like 185035664, which is the pointer value, i.e. NSNumber * when cast to NSInteger.
You should either use [dayOfWeek integerValue] or directly turn dayOfWeek into a NSInteger in your method signature.
Also I think you're getting something else wrong: from the doc of setWeekday:
Sets the number of weekday units for the receiver. Weekday units are
the numbers 1 through n, where n is the number of days in the week.
For example, in the Gregorian calendar, n is 7 and Sunday is
represented by 1.
Sunday is 1, so you'd better check the correspondence with your representation too.
See https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDateFormatter_Class/Reference/Reference.html#//apple_ref/occ/instm/NSDateFormatter/weekdaySymbols
Simply use weekdaySymbols to retrieve the dayname.
Thanx to Every one, here is a clean response :
/**
* getting the day of week string for a given day of week number
*
* #param dayOfWeekNumber 0 return sunday, 6 return saturday
*
* #return a string corresponding at the given day of week.
*/
- (NSString*) getDayOfWeekStringForDayOfWeek:(NSInteger)dayOfWeek{
return [[dateFormatter shortWeekdaySymbols] objectAtIndex:dayOfWeek];
}

Overlap of a Date Range with Other Date Ranges

Good Evening,
I am trying to figure out how to count the number of days between date ranges by comparing the date ranges. For example, I have three given ranges:
range_1 01/01/2001 to 01/01/2002
range_2 01/02/2002 to 01/01/2003
range_3 01/02/2003 to 01/01/2004
If I compare my_date_range 12/12/2001 to 01/05/2002 with the ranges above, the result should show that between range_1 and my_date_range there are 19 days, between range_2 and my_date_range there are 5 days, and between range_3 and my_date_range there are 0 days.
In Excel this was easy, I would simply use:
=SUMPRODUCT(ISNUMBER(MATCH(ROW(INDIRECT(A1&":"&B1)),ROW(INDIRECT($C$1&":"&$D$1)),0))*1)
where A1 and B1 are the start and end dates the user enters, and C1 and D1 is one of the three date ranges. I would then use the same formula and compare A1 and B1 to the second date range, then the third.
But how is this translated into objective-c? (I am able to compare two dates and get the number of days between them.)
First you have to convert the date strings to NSDate values:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MM/dd/yyyy"];
NSDate *range1Start = [dateFormatter dateFromString:#"01/01/2001"];
NSDate *range1End = [dateFormatter dateFromString:#"01/01/2002"];
NSDate *userStart = [dateFormatter dateFromString:#"12/12/2001"];
NSDate *userEnd = [dateFormatter dateFromString:#"01/05/2002"];
Then you can compute the overlapping interval:
NSDate *overlapFrom = [range1Start laterDate:userStart];
NSDate *overlapTo = [range1End earlierDate:userEnd];
And finally the number of days between the start and end date of the overlapping interval:
NSInteger days;
if ([overlapFrom compare:overlapTo] > 0) {
// Date ranges do not overlap
days = 0;
} else {
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *comp = [calendar components:NSDayCalendarUnit fromDate:overlapFrom toDate:overlapTo options:0];
days = [comp day];
}
NSLog(#"%ld", (long)days);
In this example, the output is 20, because the difference between 12/12/2001 and 01/01/2002 is 20 days. You have to add 1 if both start and end day of the overlapping range should be counted.
Once you have your start/end dates as per Martin's answer, you can use the intersection(with) function on DateInterval:
let interval1 = DateInterval(start: start1, end: end1)
let interval2 = DateInterval(start: start2, end: end2)
let intersection = interval1.insection(with: interval2)
Also helpful if you just want to check for an overlap is interval1.intersects(interval2).

How to check if the current time is within a specified range in ios? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Determine if current local time is between two times (ignoring the date portion)
In iOS, how can I do the following:
I have two NSDate objects that represent the opening and closing times for a store. The times within these objects are accurate but the date is unspecified (the store opens and closes at the same time regardless of the date). How can I check if the current time falls between in this time frame?
Note, if it would help for the opening and closing times to be in another format other than NSDate objects, I'm fine with that. Currently, I'm just reading in a date string such as "12:30" from a file and using date formatter to create a matching NSDate object.
Update: Note that this solution is specific to your case and assumes that store opening hours don't span two days. For example it won't work if the opening hour goes from Monday 9pm to Tuesday 10am. Since 10pm is after 9pm but not before 10am (within a day). So keep that in mind.
I cooked up a function which will tell you if the time of one date is between two other dates (it ignores the year, month and day). There's also a second helper function which gives you a new NSDate with the year, month and day components "neutralized" (eg. set to some static value).
The idea is to set the year, month and day components to be the same between all dates so that the comparison will only rely on the time.
I'm not sure if it's the most efficient approach, but it works.
- (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);
}
I used this code to test it. You can see that the year, month and days are set to some random values and don't affect the time checking.
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:#"yyyy:MM:dd HH:mm:ss"];
NSDate *openingDate = [dateFormatter dateFromString:#"2012:03:12 12:30:12"];
NSDate *closingDate = [dateFormatter dateFromString:#"1983:11:01 17:12:00"];
NSDate *targetDate = [dateFormatter dateFromString:#"2034:09:24 14:15:54"];
if ([self isTimeOfDate:targetDate betweenStartDate:openingDate andEndDate:closingDate]) {
NSLog(#"TARGET IS INSIDE!");
}else {
NSLog(#"TARGET IS NOT INSIDE!");
}