select/deselect random multiple dates - ios

on click I want select/deselect random multiple dates. user should be able to select multiple dates (Ex: I should be able to select 2 Dec 2014, 8 Dec 2014 and 18 dec 2014. all these three dates should look selected.). Current I m using DLSCalendar. The DLSCalendar supports single date selection and range selection.
any others lib that supports the above mention functionality is welcome
Thanks.

Changes in DSLCalendarView related to select/deselect random multiple dates.
Ex: I should be able to select 2 Dec 2014, 8 Dec 2014 and 18 dec 2014. all these three dates should look selected.
Thanks :)

Please be more precise in what you want to accomplish.
If you are trying to create random dates in objective-c you can do the following:
// Objective-c Random date picker
//SET Day integers
int lowerday = 1;
int upperday = 31;
//SET Month integers
int lowermonth = 1;
int uppermonth = 12;
//SET Year integers
int loweryear = 1;
int upperyear = 2025; //Or any random year, but always higher then loweryear!
//Generate random Date
int monthvalue = lowermonth + arc4random() % (uppermonth - lowermonth); //Month
int yearvalue = loweryear + arc4random() % (upperyear - loweryear ); //Year
//Days differ each month so we should account for that
NSArray *highmonth =#[#"1",#"3",#"5",#"7",#"8",#"10",#"12"]; //Months with 31 days
NSArray *lowmonth =#[#"4",#"6",#"9",#"11"]; //Months with 30 days
NSString *secondmonth =#"2";
NSString *random_month =[NSString stringWithFormat:#"%d",monthvalue];
int dayvalue;
if ([highmonth containsObject:random_month]) {
//Do nothing the upperday is correctly set
}else if([lowmonth containsObject:random_month]){
upperday=30;
}else if([random_month isEqualToString:secondmonth]){
//To options 28 or 29 days
if (fmod(monthvalue, 1.0) == 0.0) {
//29 Days
upperday=29;
}else{
//28 Days
upperday=28;
}
}
dayvalue = lowerday + arc4random() % (upperday - lowerday ); //Day
//Create NSDate and give our random numbers
NSString *dateString = [NSString stringWithFormat:#"%d-%d-%d",dayvalue,monthvalue,yearvalue];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd-MM-yyyy"];
NSDate *dateFromString=[dateFormatter dateFromString:dateString];
//Check Random Date
if (dateFromString==nil) {
NSLog(#"Could not create random date");
}else{
NSLog(#"Succes! The Date was: %#",dateFromString);
}

Related

(Obj-c) Identify morning, afternoon or night from a date string

I'm working in Objective-C. I have this three values in string, which they determine the part of the day
NSString *morning = #"7:01";
NSString *afternoon = #"12:01"
NSString *night = #"19:01"
And my original date is this, also in String
NSString *currentTime = #"Sat, 17 Oct 2015 9:58 am CDT"
I need to identify if the current date is morning, afternoon or night according with the current date as String. Anyone have a solution?
Your question has received a negative score (-4 at the time of writing) as people obviously feel you haven't shown the effort SO expects. However your question hides a gotcha and something which Apple recently made harder, which makes it interesting.
Your sample time is:
NSString *currentTime = #"Sat, 17 Oct 2015 9:58 am CDT"
which would seem to be "morning". However this is exactly the same time as:
Sat, 17 Oct 2015 2:58 pm GMT
which would seem to be "afternoon". Both these times are:
Sat, 17 Oct 2015 14:58 UTC
Why is this an issue?
An NSDate is a point in time without any associated time zone. The class NSDateFormatter, and associated methods on NSDate itself, will parse a date-time string and produce the absolute UTC point in time the string represents. Any time zone in the string, such as CDT in the example, is allowed for in determining the absolute time point but is not directly represented in the NSDate value that results.
When the NSCalendar class is used to break out the parts of a date it does so in relation to a time zone, which defaults to the system time zone.
What all this adds up to is if your app is running, say, on a computer in the UK and you follow the suggestion in the comments:
parse the time (using NSDateFormatter)
break out the hour & min to get an NSDateComponents value (using NSCalendar); and
compare the hour & min to your boundaries then your sample time will be reported as "afternoon"
Not good :-(
What you need is to parse the date-time (getting a standard UTC time point) and the time zone, you can then pass that time zone to NSCalendar and the rest is easy.
Apple makes it harder
Prior to OS X 10.9 & iOS 7 the NSDateFormatter class returned an NSCalendarDate date value, that type was a subclass of NSDate and also stored an NSTimeZone value. So parsing your sample returned both the time point "Sat, 17 Oct 2015 14:58 UTC" and the time zone "UTC-5". With that information NSCalendar could be used to break out the hour & min and correctly determine the time is "morning".
NSCalendarDate is now deprecated, and while it is still possible to use it this could change at any moment. Apple do not yet appear to have provide an alternative "parse date and time zone" method.
Parsing both the date and time zone offset
From the simple observation that if you parse "Sat, 17 Oct 2015 9:58 am CDT" ignoring the time zone and treating it as UTC the result is an absolute time point which differs by 5 hours, the time zone offset for CDT, from the one obtained if the string is parsed taking the time zone into account you have a method to obtain the time zone - parse the string twice, once ignoring the time zone, and determine the difference.
This may not be the best algorithm, but it does work... (you may insert here warnings about premature optimisation!)
So here goes (minimal comments, look the methods up in the documentation, error checking etc. - treat as an outline only):
- (BOOL) dateAndZoneFromString:(NSString *)timeString // the date-time string
dateFormat:(NSString *)dateFormat // the format of the date-time, should contain a time zone format at the end
parsedDate:(NSDate **)date // NSDate representing the absolute time point
parsedZone:(NSTimeZone **)zone // NSTimeZone representing the time zone of the original string
error:(NSError **)error
{
NSDateFormatter *df = [NSDateFormatter new];
// parse timeString taking time zone into account
df.dateFormat = dateFormat;
NSDate *absDate = [df dateFromString:timeString];
// parse timeString ignoring the time zone by removing the format specifier from dateFormat
df.timeZone = [NSTimeZone timeZoneWithAbbreviation:#"UTC"];
df.dateFormat = [dateFormat stringByReplacingOccurrencesOfString:#" *[zZvV]+$" withString:#"" options:NSRegularExpressionSearch range:NSMakeRange(0, dateFormat.length)];
NSDate *zonelessDate;
NSRange range = NSMakeRange(0, timeString.length);
if ( [df getObjectValue:&zonelessDate forString:timeString range:&range error:error] )
{
// parse successful, calculate the difference and construct an NSTimeZone value
NSTimeInterval offset = [zonelessDate timeIntervalSinceDate:absDate];
NSTimeZone *timezone = [NSTimeZone timeZoneForSecondsFromGMT:offset];
*date = absDate;
*zone = timezone;
return YES;
}
else
return NO;
}
If you pass #"Sat, 17 Oct 2015 9:58 am CDT" and for format #"E, d MMM y h:m a z" to this method it will return the time point "Sat, 17 Oct 2015 14:58 UTC" as an NSDate and the time zone "UTC-5" as an NSTimeZone.
If you pass #"Sat, 17 Oct 2015 2:58 pm GMT" then it will return the same absolute time point and a time zone of "UTC+0".
For this point you can use these values with NSCalendar, NSDateComponents, and simple comparisons to determine morning/afternoon/night.
HTH
-(void)ShowTimeMessage
{
// For calculating the current date
NSDate *date = [NSDate date];
// Make Date Formatter
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"hh a EEEE"];
// hh for hour mm for minutes and a will show you AM or PM
NSString *str = [dateFormatter stringFromDate:date];
// NSLog(#"%#", str);
// Sperate str by space i.e. you will get time and AM/PM at index 0 and 1 respectively
NSArray *array = [str componentsSeparatedByString:#" "];
// Now you can check it by 12. If < 12 means Its morning > 12 means its evening or night
NSString *message;
NSString *timeInHour;
NSString *am_pm;
NSString *DayOfWeek;
if (array.count>2)
{
// am pm case
timeInHour = array[0];
am_pm = array[1];
DayOfWeek = array[2];
}
else if (array.count>1)
{
// 24 hours case
timeInHour = array[0];
DayOfWeek = array[1];
}
if (am_pm)
{
if ([timeInHour integerValue]>=4 && [timeInHour integerValue]<=9 && [am_pm isEqualToString:#"AM"])
{
message = [NSString stringWithFormat:#"Morning"];
}
else if (([timeInHour integerValue]>=10 && [timeInHour integerValue]!=12 && [am_pm isEqualToString:#"AM"]) || (([timeInHour integerValue]<4 || [timeInHour integerValue]==12) && [am_pm isEqualToString:#"PM"]))
{
message = [NSString stringWithFormat:#"Afternoon"];
}
else if ([timeInHour integerValue]>=4 && [timeInHour integerValue]<=9 && [am_pm isEqualToString:#"PM"])
{
message = [NSString stringWithFormat:#"Evening"];
}
else if (([timeInHour integerValue]>=10 && [timeInHour integerValue]!=12 && [am_pm isEqualToString:#"PM"]) || (([timeInHour integerValue]<4 || [timeInHour integerValue]==12) && [am_pm isEqualToString:#"AM"]))
{
message = [NSString stringWithFormat:#"Night"];
}
}
else
{
if ([timeInHour integerValue]>=4 && [timeInHour integerValue]<10)
{
message = [NSString stringWithFormat:#"Morning"];
}
else if ([timeInHour integerValue]>=10 && [timeInHour integerValue]<16)
{
message = [NSString stringWithFormat:#"Afternoon"];
}
else if ([timeInHour integerValue]>=16 && [timeInHour integerValue]<22)
{
message = [NSString stringWithFormat:#"Evening"];
}
else
{
message = [NSString stringWithFormat:#"Night"];
}
}
if (DayOfWeek)
{
_timeLbl.text=[NSString stringWithFormat:#"%# %#",DayOfWeek,message];
}
}

Date formatter returning null in some cases (after 12:59:59)

I am receiving a JSON response as this.
{
0 = 50;
1 = 1;
2 = 4;
3 = "08:51:00";
4 = "20:51:00";
Id = 50;
day = 4;
endTime = "20:51:00";
openTime = "08:51:00";
venId = 1;
and I am using date formatters to convert string to date and then to appropriate string format by using this code.
NSDateFormatter * DateFormat = [[NSDateFormatter alloc] init];
[DateFormat setDateFormat:#"hh:mm:ss"];
NSDateFormatter * recevingDateFormatter = [[NSDateFormatter alloc] init];
[recevingDateFormatter setDateFormat:#"hh:mm aa"];
NSDate * openTime = [DateFormat dateFromString:[[_arrHoursOfOpr objectAtIndex:indexPath.row] objectForKey:#"openTime"]];
NSDate * endTime = [DateFormat dateFromString:[[_arrHoursOfOpr objectAtIndex:indexPath.row] objectForKey:#"endTime"]];
NSLog(#"the start time and end time is %#, %#", openTime, endTime);
objCell.txtDay.text = [_arr_weekdays objectAtIndex:[[[_arrHoursOfOpr objectAtIndex:indexPath.row]objectForKey:#"day"] integerValue]];
objCell.txtStartTime.text = [recevingDateFormatter stringFromDate:openTime];
objCell.txtEndTime.text =[recevingDateFormatter stringFromDate:endTime];
but somehow "openTime" is getting converted and "endTime" is returning null.
This is happening for all the strings which are above 12:59:59 i.e starting from time 13:00:00.
How can i fix that issue and support times later than 12:59:59?
hh indicates hours in the range of [1-12].
Hour [1-12]. When used in skeleton data or in a skeleton passed in an API for flexible date pattern generation, it should match the 12-hour-cycle format preferred by the locale (h or K); it should not match a 24-hour-cycle format (H or k). Use hh for zero padding.
In particular the "it should not match a 24-hour-cycle format" is important for you, because you actually want to explicitly match the 24-hour clock.
You need to use HH to support 13+ hours:
Hour [0-23]. When used in skeleton data or in a skeleton passed in an API for flexible date pattern generation, it should match the 24-hour-cycle format preferred by the locale (H or k); it should not match a 12-hour-cycle format (h or K). Use HH for zero padding.
See the unicode docs

Is there a way to detect which millennium a NSDate is in?

I have an NSDate from a string of 01/01/14. Unfortunately the strings are saved with two digits so I have no idea if the year is from 1900's or 2000's. But I want create some intelligent code to guess what millennium and century the full year is. I know for a fact (based on the application I'm creating) that the year can't be below 1900 in 99% of cases.
I have converted the date to now show four digits on but it's now being displayed as 01/01/0014.
Is there a way to detect the millennium of the NSDate as 0 and make my changes accordingly?
What I really want to do is something like this (pseudo code):
if (millennium == 0 && decade < 15 && decade > 99)
{
millennium = 2;
century = 0;
// change the date to 2000's here
}
else if (millennium == 00)
{
millennium = 1;
century = 9;
// change the date to 1900's here
}
For starters your pseudocode isn't quite right (the first if statement is an impossible condition as decade can't be less than 15 and more than 99 at the same time).
I have created a basic solution using NSDateComponents and made up my own conditions for when to change the year which you can easily change.
NSDate *date; // this is your date
NSDateComponents* components = [[NSCalendar currentCalendar] components: NSMonthCalendarUnit | NSDateCalendarUnit | NSYearCalendarUnit fromDate:date];
if([components year] < 15) // 2000 to 2015
{
[components setYear:[components year] + 2000];
}
else if([components year] < 100) // 1915 to 1999
{
[components setYear:[components year] + 1900];
}
date = [NSCalendar currentCalendar] dateFromComponents:components];
there is an oldschool stuff (from the 80s) here to convert a year in 2 digits to year in 4 digits.
int finalYear = (19 + (yearIn2Digits < 50)) * 100 + yearIn2Digits;
then you can use that finalYear value to build up the proper NSDate object.
the covered interval is always 100 years and it is up you where you'd like to draw the line. the original idea worked between 1950 and 2049 – as you see in the formula, – but you can refine it for covering better your actual bounds of years.
I wouldn't recommend hardcoding this logic.
what if you want to convert a date which is 1908 , or 2015.
A smarter way to do this is as follows :
-(BOOL)isInCurrentDecade:(NSDate*)date{
// I don't recollect the api to extract year from NSDate
NSInteger tmpYear = [date year];
NSInteger currentYear = [[NSDate date] year];
return tmpYear > currentYear%100
}
What I am doing here is that I compare 87 , 04 , 99 with current year digit's 14. and if it's between 00 and now then its current decade. This code is more robust than your's because it's relative comparison with current date
o/p of the code is as follow as of year 2014 :
87 - > NO // in 90's
99 -> NO
04 - > YES // in 2000's
12 - > YES
Edge case occurs when your date includes 1/1/14 if you want it to be filtered in current decade replace the '>' with ' >=" .
Use NSDateFormatter and its property "twoDigitStartDate". You set this to the earliest date that you want to be able to enter with a two digit year. No complicated logic needed, and easy to update. Now data entry is one thing, but storing a date "with a two digit year", that's criminal.
And it handles things like "I want to be able to store anything starting with the start of the tax year 1985 in two digits, that is April 1st 1985". Then April 1st 85 will be in 1985, while March 31st 85 will be in 2085. With no effort.

Getting date from weekday

I'm doing this app where the user inputs some days (Using UITableView, monday - sunday).
I then need the app to figure out which dates this matches with. Say it's the user sits on sunday the 15th and chooses monday and tuesday. The app will figure out the dates are monday 16th and tuesday 17th.
How would one go about that using NSDate and such? I know how to find a weekday using the date, but I want the opposite.
Of course it has to be the closest days, like not finding monday the 23rd, but finding 16th.
Hope that makes sense. :-)
A direct method, without using a loop:
NSUInteger targetWeekday = ...; // 1 = Sunday, 2 = Monday, ...
// Date components for today:
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *now = [NSDate date];
NSDateComponents *comp = [cal components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSWeekdayCalendarUnit
fromDate:now];
// Adjust components for target weekday:
if (targetWeekday >= comp.weekday) {
comp.day += (targetWeekday - comp.weekday);
} else {
comp.day += (targetWeekday + 7 - comp.weekday); // Assuming 7 days per week.
}
comp.weekday = targetWeekday;
// And back to NSDate:
NSDate *targetDate = [cal dateFromComponents:comp];
Remark:
if (targetWeekday >= comp.weekday) {
comp.day += (targetWeekday - comp.weekday);
} else {
comp.day += (targetWeekday + 7 - comp.weekday); // Assuming 7 days per week.
}
can be replaced by the shorter, equivalent code
comp.day += (targetWeekday + 7 - comp.weekday) % 7;
You can do it by following a simple procedure:
Start with an NSDate that represents today
Get the day of the week from it (here is how it is done)
If the day of the week matches what's in the selected UITableViewCell, you are done.
Otherwise, add one day to NSDate (here is how it is done), and go back to step 2.

NSMutableDictionary setObject:forKey (ios 6 without ARC) results in NULL

The following code was working prior to upgrading to iOS 6. It works in the 5.1 iPhone simulator as well, but fails with 6.0 simulator and device.
Trying to setObject:forKey in a loop to an NSMutableDictionary. Have tried adding in the loop (as the following code shows) and also tried by initializing with arrays for objects and keys which results in the same failure. Another strange bit of information is that sometimes it works but fails most of the time. The object being added is a UILocalNotification and the key is an object that represents a WeekDay (more than a simple string). The output of running is shown below. The UILocalNotifications and keys are clearly not NULL but the added pair in the MutableDictionary has NULL for some of the objects most of the time. Mostly it's the last added day (key) whose object is null. I'm completely at a loss as to how this breaking, thanks in advance for any help!
copy method for WeekDay (NSCopying Protocol):
- (id)copyWithZone:(NSZone *)zone
{
WeekDay * copy = [[WeekDay alloc] initWithDay:self.day];
return copy;
}
code snippet using setObject:forKey:
NSMutableDictionary * newAlarmsDictionary = [[NSMutableDictionary alloc] init];
NSArray * theDayKeys = [[_daysEnabledDict allKeys] sortedArrayUsingSelector:#selector(compare:)];
NSMutableArray * tempNotifyArray = [[NSMutableArray alloc] init];
UILocalNotification * theAlarm = nil;
WeekDay * theWeekDay = nil;
for (int i=0; i < [theDayKeys count]; i++) {
if ([[_daysEnabledDict objectForKey:[theDayKeys objectAtIndex:i]] boolValue] == TRUE) {
theWeekDay = [theDayKeys objectAtIndex:i];
NSDate * now = [NSDate date];
... deleted lines setting up fire date for UILocalNotification, not significant to problem ...
theAlarm = [[UILocalNotification alloc] init];
theAlarm.fireDate = itemDate;
theAlarm.repeatInterval = NSWeekCalendarUnit;
theAlarm.timeZone = [NSTimeZone localTimeZone];
theAlarm.soundName = UILocalNotificationDefaultSoundName;
theAlarm.applicationIconBadgeNumber = 0;
[newAlarmsDictionary setObject:theAlarm forKey:theWeekDay];
[tempNotifyArray addObject:theAlarm];
[theAlarm release];
}
}
}
NSLog(#"--Debug: tempNotifyArray---- %# -------------", tempNotifyArray);
NSLog(#"--Debug: newAlarmsDictionary ====== %# =============", newAlarmsDictionary);
Here is the output of the two NSlog statements at the end of the code snippet. This particular run adds 4 notifications, for days wed thru sat. The 'alarms' put into the tempNotifyArray are valid but when added to the dictionary (one in this case) is null.
2012-11-26 11:07:01.087 MedTrack[9728:11303] --Debug: tempNotifyArray---- (
"<UIConcreteLocalNotification: 0x7277940>{fire date = Wednesday, November 28, 2012, 11:06:00 AM Eastern Standard Time, time zone = America/Toronto (EST) offset -18000, repeat interval = NSWeekCalendarUnit, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Wednesday, November 28, 2012, 11:06:00 AM Eastern Standard Time, user info = {\n Temp = Fred;\n}}",
"<UIConcreteLocalNotification: 0x8883280>{fire date = Thursday, November 29, 2012, 11:06:00 AM Eastern Standard Time, time zone = America/Toronto (EST) offset -18000, repeat interval = NSWeekCalendarUnit, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Thursday, November 29, 2012, 11:06:00 AM Eastern Standard Time, user info = {\n Temp = Fred;\n}}",
"<UIConcreteLocalNotification: 0x75c6590>{fire date = Friday, November 30, 2012, 11:06:00 AM Eastern Standard Time, time zone = America/Toronto (EST) offset -18000, repeat interval = NSWeekCalendarUnit, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Friday, November 30, 2012, 11:06:00 AM Eastern Standard Time, user info = {\n Temp = Fred;\n}}",
"<UIConcreteLocalNotification: 0x75c83e0>{fire date = Saturday, December 1, 2012, 11:06:00 AM Eastern Standard Time, time zone = America/Toronto (EST) offset -18000, repeat interval = NSWeekCalendarUnit, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Saturday, December 1, 2012, 11:06:00 AM Eastern Standard Time, user info = {\n Temp = Fred;\n}}"
) -------------
2012-11-26 11:07:01.097 MedTrack[9728:11303] --Debug: newAlarmsDictionary ====== {
"[WeekDay] 6 (Sat)" = (null);
"[WeekDay] 3 (Wed)" = "<UIConcreteLocalNotification: 0x7277940>{fire date = Wednesday, November 28, 2012, 11:06:00 AM Eastern Standard Time, time zone = America/Toronto (EST) offset -18000, repeat interval = NSWeekCalendarUnit, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Wednesday, November 28, 2012, 11:06:00 AM Eastern Standard Time, user info = {\n Temp = Fred;\n}}";
"[WeekDay] 4 (Thu)" = "<UIConcreteLocalNotification: 0x8883280>{fire date = Thursday, November 29, 2012, 11:06:00 AM Eastern Standard Time, time zone = America/Toronto (EST) offset -18000, repeat interval = NSWeekCalendarUnit, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Thursday, November 29, 2012, 11:06:00 AM Eastern Standard Time, user info = {\n Temp = Fred;\n}}";
"[WeekDay] 5 (Fri)" = "<UIConcreteLocalNotification: 0x75c6590>{fire date = Friday, November 30, 2012, 11:06:00 AM Eastern Standard Time, time zone = America/Toronto (EST) offset -18000, repeat interval = NSWeekCalendarUnit, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = Friday, November 30, 2012, 11:06:00 AM Eastern Standard Time, user info = {\n Temp = Fred;\n}}";
The issue here is that you implement -copyWithZone:, but you fail to implement -isEqual:. Without knowing the full structure of your object, I cannot answer how that should be implemented, but here's a good basis:
- (BOOL)isEqual:(id)otherObject;
{
if ([otherObject isKindOfClass:[self class]]) {
WeekDay *otherWeekDay= (WeekDay *)otherObject;
if (self.day != [otherWeekDay day]) return NO;
if (self.name != [otherWeekDay name]) return NO;
return YES;
}
return NO;
}
- (NSUInteger) hash;
{
return self.day ^ [self.name hash];
}

Resources