iOS sort an NSArray of Time NSString's - ios

I need to sort an NSArray containing time NSString's such as,
NSMutableArray *times = [[NSMutableArray alloc]initWithObjects:#"09:00 AM",#"07:30 AM",#"06:45 PM",#"05:00 PM",#"12:45 AM",#"12:45 PM",#"01:00 AM",#"01:15 PM", nil];
What I need is to sort the array in ascending order of time.
Is there any way to do such a thing?

NSMutableArray *times = [[NSMutableArray alloc]initWithObjects:#"09:00 AM",#"07:30 AM",#"06:45 PM",#"05:00 PM",#"12:45 AM",#"12:45 PM",#"01:00 AM",#"01:15 PM", nil];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"hh:mm a"];
NSArray *sortedTimes = [times sortedArrayUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2)
{
NSDate *date1 = [dateFormatter dateFromString:obj1];
NSDate *date2 = [dateFormatter dateFromString:obj2];
return [date1 compare:date2];
}];
optimized version:
NSMutableArray *times = [[NSMutableArray alloc]initWithObjects:#"09:00 AM",#"07:30 AM",#"06:45 PM",#"05:00 PM",#"12:45 AM",#"12:45 PM",#"01:00 AM",#"01:15 PM", nil];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"hh:mm a"];
NSMutableArray *dates = [NSMutableArray arrayWithCapacity:times.count];
for (NSString *timeString in times)
{
NSDate *date = [dateFormatter dateFromString:timeString];
[dates addObject:date];
}
[dates sortUsingSelector:#selector(compare:)];
NSMutableArray *sortedTimes = [NSMutableArray arrayWithCapacity:dates.count];
for (NSDate *date in dates)
{
NSString *timeString = [dateFormatter stringFromDate:date];
[sortedTimes addObject:timeString];
}

You can try this code:
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"hh:mm a"];
[times sortUsingComparator:^NSComparisonResult(NSString* obj1, NSString *obj2) {
NSDate *firstDate = [formatter dateFromString:obj1];
NSDate *secondDate = [formatter dateFromString:obj2];
return [firstDate compare:secondDate];
}];

As these are strings it will be sored as
01:15, 12:25, 05:00....
And they are not either NSDate.
So you need to do is that Create a parallel array having NSDate from these strings, sort the array, and extract these values.
While implementing I solved it by novice-way
NSMutableArray *times = [[NSMutableArray alloc]initWithObjects:#"09:00 AM",#"07:30 AM",#"06:45 PM",#"05:00 PM",#"12:45 AM",#"12:45 PM",#"01:00 AM",#"01:15 PM", nil];
NSMutableArray *dates=[NSMutableArray new];
NSDateFormatter *dateFormatter=[NSDateFormatter new];
[dateFormatter setDateFormat:#"hh:mm a"];
for (NSString *stringDate in times) {
NSDate *date=[dateFormatter dateFromString:stringDate];
[dates addObject:date];
}
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"self" ascending:YES];
NSArray *descriptors = [NSArray arrayWithObject: descriptor];
NSArray *reverseOrder = [dates sortedArrayUsingDescriptors:descriptors];
[times removeAllObjects];
for (NSDate *date in reverseOrder) {
NSString *string=[dateFormatter stringFromDate:date];
[times addObject:string];
}
NSLog(#"%#",times);

For NSDate Comparison use this:
+ (BOOL)isDate:(NSDate *)date1 smallerThanAnotherDate:(NSDate *)date2
{
NSDate* enddate = date1;
NSDate* currentdate = date2;
NSTimeInterval distanceBetweenDates = [enddate timeIntervalSinceDate:currentdate];
double secondsInMinute = 60;
NSInteger secondsBetweenDates = distanceBetweenDates / secondsInMinute;
if (secondsBetweenDates <= 0)
return YES;
else
return NO;
}
So If you do not want to convert your hours to NSDate do this alone it works for me
NSArray *sortedTimes = [times sortedArrayUsingSelector:#selector(localizedStandardCompare:)];

Related

Converting DatePicker Date to UTC Format returns NULL

I have 4 UITextfileds, start date, start time and end date, end time. Then I'm sending my date and time into my UTC function, but it's returning null.
NSString *str1 = _startDateField.text;
str1 = [str1 stringByAppendingString:#" "];
str1 = [str1 stringByAppendingString:_startTimeField.text];
NSLog(#"str1 : %#", str1);
NSString *str2 = _endDateField.text;
str2 = [str2 stringByAppendingString:#" "];
str2 = [str2 stringByAppendingString:_endTimeField.text];
NSLog(#"str2 : %#", str2);
// Convert string to date object
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"dd-MMM-yyyy HH:mm"];
NSDate *date1 = [dateFormat dateFromString:str1];
NSDate *date2 = [dateFormat dateFromString:str2];
NSLog(#"%#", date1);
NSLog(#"%#", date2);
NSString *startTime = [self getUTCFormateDate:date1];
NSString *endTime = [self getUTCFormateDate:date2];
NSLog(#"str1 : %#", startTime);
NSLog(#"str2 : %#", endTime);
Coverting to UTC format:
-(NSString *)getUTCFormateDate:(NSDate *)localDate {
NSLog(#"%#", localDate);
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"UTC"];
[dateFormatter setTimeZone:timeZone];
[dateFormatter setDateFormat:#"dd-MMM-yyyy HH:mm"];
NSString *dateString = [dateFormatter stringFromDate:localDate];
NSLog(#"%#", dateString);
return dateString;
}
I want to read the date and time from my text fields and convert them into UTC format.
your code is fine and correct, I added the defaultTimeZone for get the time zone and subtract the time to utc time. I got the output.
check this
NSString *str1 = #"26-Nov-2019";
str1 = [str1 stringByAppendingString:#" "];
str1 = [str1 stringByAppendingString:#"9:35 am"];
NSLog(#"str1 : %#", str1);
NSString *str2 = #"26-Nov-2019";
str2 = [str2 stringByAppendingString:#" "];
str2 = [str2 stringByAppendingString:#"11:59"];
NSLog(#"str2 : %#", str2);
// Convert string to date object
NSDate *date1 = [self getUTCDate:str1];
NSDate *date2 = [self getUTCDate:str2];
NSLog(#"date1 %#", date1);
NSLog(#"date2 %#", date2);
NSString *startTime = [self getUTCFormateDate:date1];
NSString *endTime = [self getUTCFormateDate:date2];
NSLog(#"str1 : %#", startTime);
NSLog(#"str2 : %#", endTime);
-(NSDate *)getUTCDate:(NSString *)currentDate {
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"dd-MMM-yyyy HH:mm"];
NSDate *date1 = [dateFormat dateFromString:currentDate];
if (date1 == nil) {
[dateFormat setDateFormat:#"dd-MMM-yyyy hh:mm a"];
date1 = [dateFormat dateFromString:currentDate];
}
return date1;
}
-(NSString *)getUTCFormateDate:(NSDate *)localDate {
NSLog(#"%#", localDate);
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"UTC"];
[dateFormatter setTimeZone:timeZone];
[dateFormatter setDateFormat:#"dd-MMM-yyyy HH:mm"];
NSLocale *twelveHourLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
dateFormatter.locale = twelveHourLocale;
NSTimeInterval timeZoneoffset = [[NSTimeZone defaultTimeZone] secondsFromGMT];
NSTimeInterval utcTimeInterval = [localDate timeIntervalSinceReferenceDate] - timeZoneoffset;
NSDate *utcCurrentDate = [NSDate dateWithTimeIntervalSinceReferenceDate:utcTimeInterval];
NSString *dateString = [dateFormatter stringFromDate:utcCurrentDate];
NSLog(#"dateString %#", dateString);
return dateString;
}

How to connect viewcontroller to NSObject class file?

I want to connect and pass the action from ViewController to NSObject class file. In my viewcontroller, there is UISwitch Button and if I switch I want to work it in NSObject class file.
When switch is ON from viewcontroller (UIView) then the action have to work in NSObject class file.
I'm coding with Objective-C.
Here is my ViewController.m and I did this in only ViewController file. Not connected to NSOBject class file.
- (void)viewDidLoad{
[super viewDidLoad];
//UISwitch work at viewDidload
[self.mySwitch addTarget:self
action:#selector(stateChanged:) forControlEvents:UIControlEventValueChanged]; }
- (void)stateChanged:(UISwitch *)switchState{
NSLog(#"current calendar: %#", [[NSCalendar currentCalendar] calendarIdentifier]);
//get the date today
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterMediumStyle];
[formatter setCalendar:[NSCalendar currentCalendar]];
NSString *dateToday = [formatter stringFromDate:[NSDate date]];
NSLog(#"Today Date is: %#", [NSDate date]);
self.myLabel.text=dateToday;
if ([switchState isOn]) {
//[formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en_US#calendar=japanese"]];
[formatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierJapanese]];
[formatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSString *dateToday = [formatter stringFromDate:[NSDate date]];
UILabel *dtDate = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320.0f, 20.0f)];
[dtDate setText:dateToday];
self.myLabel.text =dateToday;
NSString *locale = [[NSLocale currentLocale] localeIdentifier];
NSLog(#"current date is: %#", dateToday);
NSLog(#"current locale: %#", locale);
} else {
//[formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en_US"]];
[formatter setCalendar:[NSCalendar autoupdatingCurrentCalendar]];
[formatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSString *dateToday = [formatter stringFromDate:[NSDate date]];
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320.0f, 20.0f)];
[myLabel setText:dateToday];
self.myLabel.text =dateToday;
// NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// [formatter setDateStyle:NSDateFormatterMediumStyle];
NSString *locale = [[NSLocale currentLocale] localeIdentifier];
NSLog(#"current locale: %#", locale);
NSLog(#"%#", [formatter stringFromDate: [NSDate date]]);
}
}
If you need just an action then use class methods else create a global variable or a notification observer in NSObject extended class when you get call back from the switch.
- (void)callback:(id)sender
{
[MyObject switchState:sender.state];
}

PHFetchOptions predicate with NSDate compare

Hello I had been working with Photos.framework but now I am stuck with predicate comparison of PHFetchOptions class in documents I see that we can use startDate to use in predicate. So my code is this
#interface ViewController ()
{
NSMutableArray * moments;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
moments = [NSMutableArray array];
if([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusNotDetermined)
{
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
[self loadCollections];
}];
}else
{
[self loadCollections];
}
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self loadCollections];
}
- (NSDate*)dateAddingDays:(NSInteger)days ToDate:(NSDate*)argDate
{
NSCalendar * gregorian = [NSCalendar currentCalendar];
NSDateFormatter * formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:#"dd.MM.yyyy"];
NSString * dateString = [formatter stringFromDate:argDate];
NSDate * toWorkDate = [formatter dateFromString:dateString];
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:days];
NSDate *date = [gregorian dateByAddingComponents:comps toDate:toWorkDate options:0];
NSLog(#"%#",[formatter stringFromDate:date]);
return date;
}
- (void)loadCollections
{
PHFetchOptions * options = [[PHFetchOptions alloc]init];
options.predicate = [NSComparisonPredicate predicateWithFormat:#"startDate > CAST(%d,\"NSDate\")",[self dateAddingDays2:-1 ToDate:[NSDate date]].timeIntervalSince1970];
PHFetchResult * result = [PHAssetCollection fetchMomentsWithOptions:options];
if(result != nil)
{
NSLog(#"%i",result.count);
for (int i = 0; i < result.count; i++) {
NSLog(#"%#",[result objectAtIndex:i]);
[moments addObject:[result objectAtIndex:i]];
}
}
}
So my problem is this, I need fetch fotos from one day ago, I can make this work!! any help will be appreciated.
This is the answer, basically I replaced
- (NSDate*)dateAddingDays:(NSInteger)days ToDate:(NSDate*)argDate
{
NSCalendar * gregorian = [NSCalendar currentCalendar];
NSDateFormatter * formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:#"dd.MM.yyyy"];
NSString * dateString = [formatter stringFromDate:argDate];
NSDate * toWorkDate = [formatter dateFromString:dateString];
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:days];
NSDate *date = [gregorian dateByAddingComponents:comps toDate:toWorkDate options:0];
NSLog(#"%#",[formatter stringFromDate:date]);
return date;
}
by
- (NSDate*)yesterday
{
NSCalendar * gregorian = [NSCalendar currentCalendar];
return [gregorian startOfDayForDate:[gregorian dateByAddingUnit:NSCalendarUnitDay value:-1 toDate:[NSDate date] options:NSCalendarWrapComponents]];
}
and also replace this
options.predicate = [NSComparisonPredicate predicateWithFormat:#"startDate > CAST(%d,\"NSDate\")",[self dateAddingDays2:-1 ToDate:[NSDate date]].timeIntervalSince1970];
by this
options.predicate = [NSComparisonPredicate predicateWithFormat:#"(startDate > %#)",[self yesterday]];
and now is working!!! thanks to #Larme

Find out next most close date from NSDate array of times

How can I find out the next prayer from the array of times, I have total 6 Prayers at different times and i want to compare each one with current time and have to find out which one is most near as a next prayer, Date format also creating problems because it give always in UTC format and I have to use local time zone, I am using the following code:
NSMutableArray *arrayTimeIntervals = [[NSMutableArray alloc]init];
NSMutableArray *intervals = [[NSMutableArray alloc]init];
NSMutableArray *arrayPrayers = [[NSMutableArray alloc]init];
[arrayPrayers addObject:#{#"prayer":#"prayer 1",#"time":#"1:12 am"}];
[arrayPrayers addObject:#{#"prayer":#"prayer 2",#"time":#"5:45 am"}];
[arrayPrayers addObject:#{#"prayer":#"prayer 3",#"time":#"12:03 pm"}];
[arrayPrayers addObject:#{#"prayer":#"prayer 4",#"time":#"3:30 pm"}];
[arrayPrayers addObject:#{#"prayer":#"prayer 4",#"time":#"6:20 pm"}];
[arrayPrayers addObject:#{#"prayer":#"prayer 6",#"time":#"7:50 pm"}];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"hh:mm a"];
NSMutableArray *dates = [NSMutableArray arrayWithCapacity:arrayPrayers.count];
for (NSDictionary *timeDict in arrayPrayers)
{
NSString *timeString = [timeDict objectForKey:#"time"];
NSString *name = [timeDict objectForKey:#"prayer"];
NSDate *date = [dateFormatter dateFromString:timeString];
[dates addObject:#{#"prayer":name,#"time":timeString, #"date":date}];
}
for (int i =0 ; i<arrayPrayers.count; i++) {
NSDictionary *timeDict = arrayPrayers[i];
NSString *timeString = [timeDict objectForKey:#"time"];
//NSString *name = [timeDict objectForKey:#"prayer"];
NSDate *date = [dateFormatter dateFromString:timeString];
NSComparisonResult result = [[NSDate date] compare:date];
if(result==NSOrderedAscending){
NSLog(#"next prayer");
}else if(result==NSOrderedDescending){
NSLog(#"last prayer");
}else{
NSLog(#"current prayer");
}
if ([date earlierDate:[NSDate date]]) {
NSTimeInterval interval = [date timeIntervalSinceNow];
NSDictionary *tempDict = #{#"Prayer":timeDict,
#"Time":timeString,
#"Index":[NSString stringWithFormat:#"%d",i],
#"Interval":[NSString stringWithFormat:#"%f",interval]};
[arrayTimeIntervals addObject:tempDict];
[intervals addObject:[NSString stringWithFormat:#"%f",interval]];
}
}
NSNumber * min = [intervals valueForKeyPath:#"#min.doubleValue"];
NSUInteger index = 0;
for(int i =0 ; i<intervals.count; i++)
{
NSDictionary* dict = arrayTimeIntervals[i];
if([[dict objectForKey:#"Interval"] intValue] == [min intValue]) {
index = i;
NSLog(#"next prayer is!!!:%ld",index);
break;
}
}
NSDictionary *dict = [arrayTimeIntervals objectAtIndex:index];
NSLog(#"next prayer object is:%#",dict);

How to correctly generate timestamp

I have a method that to create timestamp in long long integer format
EX: 1386752892
+ (NSNumber *)currentTimestampWithLongLongFormat
{
double timeStamp = ceil([[NSDate date] timeIntervalSince1970] * 1000);
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setGeneratesDecimalNumbers:false];
NSNumber *timeNumber = [NSNumber numberWithDouble:timeStamp];
NSString *timeString = [formatter stringFromNumber:timeNumber];
// NSTimeInterval is defined as double
return [NSNumber numberWithLongLong:[timeString longLongValue]];
}
But this will generate 13 digitals number
EX: 1386752811802
How to fix the problem and generate the correct format of number?
int timestamp = [[NSDate date] timeIntervalSince1970];
Try this
/**
* #param nil
* #return current time in mili second
*
* Fetch the current time stamp
*/
-(NSString *)currentTimeStamp {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSTimeZone *gmt = [NSTimeZone timeZoneWithName:#"GMT"];
[dateFormatter setTimeZone:gmt];
NSString *timeStamp1 = [dateFormatter stringFromDate:[NSDate date]];
NSDate *curdate = [dateFormatter dateFromString:timeStamp1];
double unix_timestamp = [curdate timeIntervalSince1970];
NSString *timeStamp = [NSString stringWithFormat:#"%f",unix_timestamp*1000];
return timeStamp;
}
+ (NSString*) dateFromString:(NSString*)aStr
{
NSDateFormatter *formater = [[NSDateFormatter alloc] init];
[formater setDateFormat:#"yyyy-MM-dd HH:mm"];
NSDate *date2 = [formater dateFromString:aStr];
[formater setDateFormat:#"d MMM,yyyy HH:mm"];
NSString *result = [formater stringFromDate:date2];
return result;
}
+ (NSString *)calculateTime:(NSString *)datetime :(NSString *)servertime
{
NSString *time;
NSDate *date1;
NSDate *date2;
{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
date1 = [formatter dateFromString:datetime];
date2 = [formatter dateFromString:servertime];
}
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *differenceComponents = [calendar components:(NSDayCalendarUnit)
fromDate:date1
toDate:date2
options:0];
NSTimeInterval interval = [date1 timeIntervalSinceDate: date2];//[date1 timeIntervalSince1970] - [date2 timeIntervalSince1970];
int hour = interval / 3600;
int minute = (int)interval % 3600 / 60;
int seconds = (int)interval % 60;
hour=ABS(hour);
minute=ABS(minute);
seconds=ABS(seconds);
if ([differenceComponents day]>0) {
time= [NSString stringWithFormat:#"%ld %#", (long)[differenceComponents day],[NSString stringWithFormat:NSLocalizedString(#"daysago", nil)]];
}
else
{
if ([differenceComponents day] == 0) {
time= [NSString stringWithFormat:#"%ld %#", (long)[differenceComponents day],[NSString stringWithFormat:NSLocalizedString(#"dayago", nil)]];
if (hour>0) {
time= [NSString stringWithFormat:#"%d %#", ABS(hour),[NSString stringWithFormat:NSLocalizedString(#"hourago", nil)]];
}
else {
time= [NSString stringWithFormat:#"%d %#", ABS(hour),[NSString stringWithFormat:NSLocalizedString(#"hoursago", nil)]];
if (minute>0) {
time= [NSString stringWithFormat:#"%d %#", ABS(minute),[NSString stringWithFormat:NSLocalizedString(#"minuteago", nil)]];
}
else {
time= [NSString stringWithFormat:#"%d %#", ABS(minute),[NSString stringWithFormat:NSLocalizedString(#"minuteago", nil)]];
if (seconds>0) {
time= [NSString stringWithFormat:#"%d %#", ABS(seconds),[NSString stringWithFormat:NSLocalizedString(#"secondago", nil)]];
}
else {
time= [NSString stringWithFormat:#"%d %#", ABS(seconds),[NSString stringWithFormat:NSLocalizedString(#"secondsago", nil)]];
}
}
}
}
}
return time;
}
/// as per requirement we will use date formats

Resources