Converting time strings to dates and finding the upcoming one - ios

In my program, I have an NSArray of various dates and times, stored as strings and formatted like this: #[#"07:23",#"18:09",#"13:55"];
When I use an NSDateFormatter to convert these to NSDates, the times are correct, but year/month/day information is added.
The arrays that I have created are columns of a bus schedule. Each entry is one timeslot for whatever stop the array represents. My application needs to take the current time: [NSDate date] and see which time from the array is next in sequence. I'm just trying to display when the very next bus will arrive.
I have thought of comparing each element of the array with the current date and time using -[NSDate's laterDate:], but the problem is that when I convert the strings to NSDate objects, it gives them some random day-month-year like 13:55:00 January 1st, 2001 which will always be before the current date, so my test won't work.
I can find some workarounds that are really tragically McGuyvered but I would prefer something clean.
What I want to know are these things:
Can I remove the day/month/year portion from the NSDate?
Is it possible to easily set the day/month/year of each object in my array to today without using NSDateComponents and NSCalendar? I can manipulate them as they enter the array.
Would it be easier to reformat the current date/time to match the day/month/year of the array?
Otherwise, is there a better, cleaner solution to find the next upcoming timeslot? I am open to changing the entire format from arrays if necessary.

Can I remove the day/month/year portion from the NSDate?
No. An NSDate is merely an instant in time that is some number of seconds since some reference date. Describing that instant in time as some year/month/day depends on the local calendar. For example, the "day of month" of [NSDate date] as I type this is 28 where I live but 29 for the same NSDate value in Japan.
Is it possible to easily set the day/month/year of each object in my
NSMutableArray to today? without using NSDateComponents and
NSCalendar?
No. That's what NSDateComponents is for.
Otherwise, is there a better, cleaner solution to find
the next upcoming timeslot? I am open to changing the entire format
from arrays if necessary.
Use NSCalendar's -components:fromDate: to get an NSDateComponents object that matches [NSDate date]. Replace the hour/minute/second components with an arrival time's hour/minute/second: this is an arrival time today. Add one to the day component: this is an arrival time tomorrow. (Weekend and holiday schedules cause extra complication; the weekday component may be useful.) Convert back to NSDate using NSCalendar's -dateFromComponents: and perform your date comparisons there.

Related

Need a time object in one of my iOS app (Swift)

I am currently creating an app where I ask the user to input a time (through datePicker) and send the user a notification every day on that time.However, I noticed that datePicker only has an NSDate object, and was wondering if there was a Time object counterpart.Also, would this Time object be a good way of storing the time, or should I convert the hour and minutes to Integers for storage?
Thanks in advance!
NSDate also contains Time information within it. You can store the exact date and time using only NSDate.
NSDate is a generic representation independent of any time zone. According to the apple docs:
NSDate objects encapsulate a single point in time, independent of any particular calendrical system or time zone. Date objects are immutable, representing an invariant time interval relative to an absolute reference date (00:00:00 UTC on 1 January 2001)
NSDate is basically the number of seconds from the reference date mentioned above.
And yes NSDate is the best way for storing time and date information in your app.
Whenever you want to display the time, use NSDateFormatter to format the date and time into any format you desire and for any Time Zone you require.
Swift 3
The NSDate class has been renamed to Date in Swift 3

NSDate format time with start and end in hours

Is there a way to format time so that it shows up as
19-Oct-2015 3-6 PM? I know how to set day, month, year. I just need to know if it's possible to set the hours so that it shows a timeframe like 3pm-6pm or if I will just have to format the strings myself.
You will have to format at least the time portion yourself.
NSDateFormatter formats NSDate. NSDate is something which denotes single point in time. It seems like you want to define time with range ie. at least two different NSDates. So, it might not be possible to do that with only NSDateFormatter. If both date start date and end date lie on the same date, you could use NSDateFormatter to format time and then get components of hour for two different date, then compose the string to have it like you showed above.

Best way to store the day of the week using NSDate and NSDateFormatter

I'm trying to reproduce some of the functionality of the default Clock where I let users select a repeat frequency for an alarm. The problem is that different NSCalendar settings will give you different names for the days of the week. How do I store the selected days of the week in such a way that if the user changes their calendar the frequency always falls on the right day of the week?
One solution would be to check if the calendar has changed every time the app comes into foreground, and if so, make appropriate changes from there. Probably not the most elegant solution, nor the best practice, but it could get the job done.
Take (long) [dateYouWantToRemember timeIntervalSince1970] and store that in a property file or some such. (You could use timeIntervalSinceReferenceDate, but the 1970 number is the "UNIX epoch date" and more standardized -- you can find converters online to check it.)
Later, under the (potentially) different calendar, do [NSDate dateWithTimeIntervalSince1970:theLongYouStored] and you will reconstruct the date, in the new calendar.
Now use NSCalendar/NSDateComponents to find out the new ordinal day of week of that date, and use [NSDateFormatter weekdaySymbols] to fetch a list of the weekday names. Index the list with the ordinal to fetch the new day name. Use NSDateComponents to do arithmetic on you dates to select the next date that is that day of the week, as needed for your app.

change date of NSDate while keeping the time same

I get current time or time stamp of some image. I have to change only date while the time should not be changed. For example I use [NSdate date] to get current date and time and store in an NSdate object that is "2014-01-10 09:58:47 +0000". Now change only the date part, keeping the time same as it is "2013-11-09 09:58:47 +0000"
How can I achieve that?
Convert the date into it's date components (which includes the time part), change the date part of the components to be for the new day, and create a new date based on these components.
dateByAddingDateComponents is also another way to do it.
It's all described in the Calendrical Calculations documentation.

How to create NSDates (begin and end of day) without using NSCalendar?

I have an iPad app, using XCode 4.5, iOS 6.0 and Storyboards. I need to create a NSCompoundPredicate using a NSDate, which I am given by the user selecting from UIDatePicker. The examples I have seen show the use of NSCalendar and NSCalendarComponents, both of which use the "default" calendar.
This is the code, using one NSPredicate, which works but gets all of the records for that date and all dates in the future, which is wrong.
NSMutableArray *apptDataArray = [NSMutableArray new];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(aStartTime = %#)", [dict objectForKey:#"selectedDate"]];
I need to use a NSCompoundPredicate because I need to get all of the records for a particular date (from 1 minute after midnight to midnight of the selected date).
Is there a way to create two NSDates (begin and end of the day) for the NSCompoundPredicate from a given NSDate, in this case: [dict objectForKey:#"selectedDate"] (which is a NSDate)? (This question is NOT a duplicate of this which uses the NSCalendar code mentioned above.)
UPDATE: updated question in bold.
While you say that you don't want to use a NSCalendar, you already are:
From the UIDatePicker Class Reference:
calendar
The calendar to use for the date picker.
#property(nonatomic, copy) NSCalendar *calendar
Discussion
The default value of this property corresponds to the user’s current calendar as configured in Settings. This is equivalent
to the value returned by calling the NSCalendar class method
currentCalendar. Setting calendar to nil is equivalent to setting it
to its default value.
Calendars specify the details of cultural systems used for reckoning
time; they identify the beginning, length, and divisions of a year.
Basically, the only way to get accurate values that you can use for a query is to use the same calendar that was used to create your NSDate. So, the short version is: Go ahead and use a calendar. In fact, use this one:
NSCalendar *cal = [NSCalendar currentCalendar];
You can't really create a meaningful NSDate object without referencing a calendar at some point. As others have pointed out, an NSDate is stored as the number of seconds since a particular date and time. Unless you feel like completely re-writing all calendar operations in order to account for things like leap years, leap seconds, etc you should use what Apple has already given us.
An NSDate represents the number of seconds since a fixed epoch. Internally, the epoch used is January 1, 2001 12:00:00AM UTC+0. Most APIs across platforms use another epoch, January 1, 1970 12:00:00AM UTC+0, called the "UNIX epoch" or "time_t epoch", so there are APIs to convert to/from that epoch as well. As a result, a date is just a single number, of type NSTimeInterval (a typedef of double.)
To get the first and last moments of a day, you need to define a "day." This is done with a calendar. Most calendars have 24-hour days, but I'm sure there's one out there that doesn't.
You say you cannot use NSCalendar because you need to work in a calendar that it does not support. Can you tell us which calendar you need to use?
To my mind its not possible (why you don't want to use NSCalendar?)

Resources