I want to store times type value (but not the date) in Core Data. Which data type should I use?
Possible options:
Three integer attributes for hour, minutes, seconds.
One string attribute for "HH:MM:SS".
One integer attribute for the number of seconds since midnight.
The best representation depends on what type of queries involving the time you want to
execute. The first option is better if you want to search for a given hour, minute or second. The other options are better if you have to search for time intervals.
My approach would probably be to convert it to an HHMMSS format, either as an integer or a string. NSDate isn't appropriate because it is stored as a interval since an epoch (seconds since 1970)
The date portion of an NSDate is inherently part of time. NSDate is a NSTimeInterval number of seconds positive or negative since the reference date. With a locale and a timezone you can get an appropriate localized display string on the fly.
In most cases it makes far more sense to store the number behind the NSDate returned by timeIntervalSinceReferenceDate
It's small and portable and correct.
Then recreate an NSDate with dateWithTimeIntervalSinceReferenceDate:
Then use an NSDateFormatter with NSLocale and NSTimeZone to get an appropriate value for display to users.
It's an unwieldy and cumbersome set of tools that actually help you do it right.
The good news is all the effort you expend in doing this pays off in making it easier next time and giving you code that will do the right thing and have a backing value that is actually really easy to store and manipulate.
Additionally by using the API correctly you will lose no precision and have more possibilities open to you.
Trying to do it with format strings alone seems easy and simple but is the road to bad code.
Related
Given an NSTimeInterval representing a period of time, how do I create a human-readable string that expresses that time period in a way that respects i18N?
For example, if the NSTimeInterval is equal to 10823.23435 seconds, then some reasonable ways of rendering that as a string for those in the US might be:
3:23
3 hours, 23 seconds
etc.
(I.e., stuff you'd see on a stopwatch.)
Presumably other locales might use different renderings.
I'm aware of NSDateFormatter and NSNumberFormatter, but it's not clear to me if or how to use one of these for this problem.
I'm also aware of FormatterKit, but that only does relative time periods (e.g., "3 minutes ago"). I'm looking for absolute time periods.
It is trivial to cook up my own locale-specific solution, but has this problem been solved properly already?
Thanks.
For iOS 8 there are NSDateComponentsFormatter & NSDateIntervalFormatter, they may work for your application.
Docs are lacking see NSHipster: NSFormatter
and
Foundation/NSDateIntervalFormatter.h
I just have a quick question about how date and time works in iOS and Objective-C. If I make a call like NSDate *today = [NSDate date] on two separate devices, will they both return the exact same time? I am trying to have multiple phones sync up using the current time and I just want to make sure that they will have the same current time (if it's a matter of milliseconds I'm not worried but more than a second off will probably not work).
Thanks in advance!
Since NSDate stores a time internally as an NSTimeInterval, which is a typedef for double. It has in the sub-microsecond resolution for times within a decade or more of the date of this question.
This means that even if your two devices have closely synchronized clocks, you are unlikely to get exactly the same NSDate by calling [NSDate date] on both devices.
You can check whether two dates are within a second of each other like this:
NSTimeInterval diff = date0.timeIntervalSinceReferenceDate - date1.timeIntervalSinceReferenceDate;
if (fabs(diff) < 1) {
// dates less than one second apart
}
The Using Time Zones Guide
shows how to check if daylight saving time (DST) is in action for the current date and how to get the next date when daylight saving time changes. With calls to:
isDaylightSavingTime
daylightSavingTimeOffset
nextDaylightSavingTime
E.g.
Bool isDST = [[NSTimeZone systemTimeZone] isDaylightSavingTime];
But I need to find out if a future date is DST or not so that when users scroll to a distant and far off date, they can see my graph plotted with the time axis labelled correctly (GMT or BST).
The problem is that isDayLightSavingTime seems to take two parameters, one passed to it explicitly (NSTimeZone) and the other implicitly, namely the current system time.
You just need to call isDaylightSavingTimeForDate, passing in the relevant NSDate.
It's not that isDaylightSavingTime itself has two parameters - it's that it calls isDaylightSavingTimeForDate with the current date. From the docs for isDaylightSavingTime:
This method invokes isDaylightSavingTimeForDate: with the current date as the argument.
So just skip the "convenience" method and call isDaylightSavingTimeForDate specifying the date you want to check. (I'd give some sample code, but the chances of me getting Objective C syntax correct are very slim...)
Looking at the docs there is a descrepancy between the data in a checkin object for the query API s the push API with regards to timeZone.
According to https://developer.foursquare.com/overview/realtime a sample push will contain the name of the tz eg America/New_York
However according to https://developer.foursquare.com/docs/responses/checkin (and the API explorer) a checkin object will contain the timeZone offset eg 60 for GMT+1
I havn't managed to confirm whats in the Push API myself yet as I hav to setup the SSL certs, can anyone confirm of the docs are correct and we do indeed have 2 type of tz format. I would have thought that including the timeZone rather than the offset would be better as this doesn't vary with Daylight Savings unlike the figure. Europe/London will always be a constant where as the offset will switch between 0 and 60 mins
I'm not directly familiar with FourSquare's API, so I can't confirm or deny this for you. But I can tell you there are often cases where you would use both.
It is ok to only present an offset, if the data represents a particular time. Since the checkin response provides a createdAt date/time as an integer seconds since epoch (aka a "Unix Timestamp"), then it is appropriate to provide a separate offset. (Although I find it interesting that they provide the offset as a string and not as an integer number of minutes.) The other way you might do this would be with a single DateTimeOffset values, usually presented in ISO8601 format, as in 2013-06-02T01:23:45-07:00. Either are acceptable.
But as you may be aware, an offset does not uniquely identify a time zone. In the case of a single event, it doesn't need to. But if it were a recurring event, or if there was a possibility that you might want to modify the time value, then an offset alone would not suffice. That's when you need the full zone identifier.
If you have a zone identifier such as America/New_York, then you can always find out what the correct offset for any date/time would be. But not everyone has a TZDB implementation readily available. For example, in .Net on Windows, you get Microsoft's clumsy time zone database by default, and you have to find a library (like NodaTime) if you want to use the TZDB zones.
It does seem strange that the push and pull for the same type of action (a check-in) would have different values just because they were going through different APIs. My advice (to Foursquare) would be threefold:
Be consistent about the data for the same activity, regardless of push vs pull.
Provide both the TZDB identifier, and the the UTC offset associated with the event.
Provide the event's timestamp and offset in a single value, as an ISO8601 formatted string, rather than a unix time integer.
The Foursquare documentation is correct but a bit incomplete (as of time of posting). The check-in response contains a timeZoneOffset field. The real-time push response has a timeZone field and a timeZoneOffset field—the timeZone field is still there for legacy purposes.
Thanks for pointing this out; we'll update the docs to reflect that timeZoneOffset is the preferred method at this point. As Matt mentioned, the offset method is a better way to identify a particular time from createdAt.
Apparently neither java.util.Date nor java.util.Calendar implement Persistable, so cannot be used in Persistable classes. What is the best alternative for persisting dates and times?
You could write your code to expect that dates and times are kept in the Unix epoch format (number of seconds since 1/1/1970). Then your problem is simply a matter of storing a long number.
storing as a long as Dan mentions is the way to go. System.currentTimeMillis() will return milliseconds since Unix Epoch, which is 1/1/1970 GMT. It's obviously fairly trivial to convert between seconds and milliseconds. For timezone corrections, the Calendar class can help you handle this.
Note:
getInstance(Timezone zone)
getTimeInMillis()
setTimeInMillis(long millis)
setTimeZone(Timezone value)