The problem is as follows :
Quick details of the app : Sorting of data (ascending) according to the date.
The UNIX date / long date from the web service in form of JSON (is of 13 digits). When the long date is parsed, I get an invalid value of the date.
Long date : 1428498595000
Converted date : Sun, 26 Apr 47237 13:16:40 (After parsing)
[Notice the year]
When the online converter is used (example) : http://www.onlineconversion.com/unix_time.htm , the same output is reproduced.
My purpose is to get the dates sorted in ascending order, but unfortunately, as the year is shown irrelevant, it makes sorting impossible.
Long date 1428498595 (After manually removing three zeros to test it on the website) : Wed, 08 Apr 2015 13:09:55 GMT (This is the correct date that needs to be shown)
Can anyone help me understand what can be done so that we could manually remove the last three zeros?
[Storing the parsed data in SQLite and then producing the stored data in UITableView]
This is in AppDelegate
+(NSString * )convertUnixTime_to_SytemTime :(NSTimeInterval )timeInterval
{
NSDate * convertedDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"YYYY-MM-DD";
NSTimeZone *localTime = [NSTimeZone systemTimeZone];
[dateFormatter setTimeZone:localTime];
NSString *timeStamp = [dateFormatter stringFromDate:convertedDate];
return timeStamp;
}
This is in the code
data.News_LastModifiedDate = [AppDelegate convertUnixTime_to_SytemTime:[[subcomponents objectAtIndex:2] doubleValue]];
Thanks much in advance.
The date/time is in milliseconds since UNIX epoch, instead of seconds. You can divide by 1000.0 in order to keep the fractional seconds (if they ever appear):
NSTimeInterval seconds = (NSTimeInterval)1428498595000 / 1000.0;
EDIT. To address other aspects of your question:
Storing the parsed data in SQLite and then producing the stored data
in UITableView
Store it as is; as a 64-bit int.
+(NSString * )convertUnixTime_to_SytemTime :(NSTimeInterval )timeInterval
This method doesn't convert the UNIX time to system time; it formats the date into a string (wrongly by the look of it). Forget it and use just the first line of code only:
NSDate * convertedDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
Where timeInterval is the original number converted to seconds as above. The only time you want the date as a string is during presentation, not during processing.
Your timestamp is in Milliseconds. Simply divide it by 1000 to get the correct date/time.
data.News_LastModifiedDate = [AppDelegate convertUnixTime_to_SytemTime:[[subcomponents objectAtIndex:2] doubleValue]/1000];
Should work for you.
Whenever you read JSON data, there should be an API description that tells you what data is delivered in which form. You would read the API description and do whatever needs doing. If there is no API description, you do whatever you can.
When you read a date from JSON data, you should as the first step convert whatever you find to an NSDate*. JSON has no built-in date type. It has a standard format for dates, using RFC3339, but your JSON doesn't do that. Apparently it uses UTC in milliseconds since 1970, stored as an integer. The JSON parser would return this as an NSNumber. That's fortunately quite easy to handle:
NSNumber* dateAsNumber = "whatever is needed to extract the integer";
NSTimeInterval dateAsInterval = [dateAsNumber doubleValue] / 1000;
NSDate* dateAsDate = [NSDate dateWithTimeIntervalSince1970: dateAsInterval];
You shouldn't convert NSDate to anything else. NSDate is the standard type for handling dates on iOS. CoreData will handle it. If you use SQL directly, convert it just before storing to the database and after loading from the database and use NSDate everywhere else.
BTW. What is SystemTime? If you use a method name like convertUnixTime_to_SytemTime, I get very worried, because no two people will ever agree what system time is. And your method doesn't return a system time, it returns something converted to a string.
Related
currently I have a piece of code that is converting a set of string (eg. 900130) keyed in by user to a date using yyMMdd(Malaysia IC) format. My code for converting the string as follows:
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyMMdd"];
date = [dateFormat dateFromString:temp]; // temp = string key in by user
The problem didn't occur to me when I was running some test, but when I gave it to someone else to test it, the problem occur where the string 490130 which should be converted to 30/1/1949 was converting it to 30/1/2049.
How do I convert 490130 to 30/1/1949 instead of 30/1/2049
NSDateFormatter assumes 20xx for a 2-digit year if the year is less than 50 and 19xx for a 2-digit year if the year is greater than 50. I forget which it assumes when the year is 50.
It seems you want a cutoff different from 50. There is no built-in support for using a different cutoff.
One option is to look at the first two characters and see if it is below or after your cutoff. Then prepend either 19 or 20 to the start of the string as needed. Then parse the string using yyyyMMdd.
I have two different values of timestamp on same day in different time. So I want to provide format 'yymmdd' to the NSDate to covert date into timestamp since the value changes acc. to time. If anyone could help me in this or suggest me since i am new to Swift.
I was a bit confused about what you were asking for but after reading your own comments/answers to the original post I understand that you are looking for "the epoch unix timestamp". You can easily get this from any NSDate object as follows:
NSDate *yourDate = [NSDate date];//now in this example
NSTimeInterval epochTimestamp = [yourDate timeIntervalSince1970];
NSString *epochTimestampString = [#(epochTimestamp) stringValue];
NSLog(#"%#",epochTimestampString);
This way you will get the epoch timestamp defined as the number of seconds that have elapsed since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970.
Before flagging this question as a duplicate, please read on.
I need to compare two NSDates. A date I get from a server with the current date.
From NSDate.date() I get this date 2014-09-25 12:48:23 +0000 which is wrong (the time part). I needed to add 5 hours to get the current time so I did the following.
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd hh:mm:ss ZZZZZ"
let dateString = formatter.stringFromDate(NSDate.date())
The result is the correct date - 2014-09-25 06:21:56 +05:30
But there's a little hitch. This date is a String, not a NSDate. I need it to be a NSDate object to compare it with another date.
I tried converting it back like this,
let date = formatter.dateFromString(dateString)
And I get a wrong result - 2014-09-25 00:55:53 +0000. I tried passing the date string to a new NSDateFormatter to see if that works but again I still I get the wrong date.
My question is, how can I convert this date string to a NSDate object which also retains the correct time.
Thank you.
You are thoroughly confused about NSDate.
An NSDate is a point in time. It has no time zone information. If we both call [NSDate date] right now, we will get the same NSDate, even when you are in India and I'm in the UK. That's intentional. It's the same time. The time displayed on my watch and on your watch is different, but NSDate is the same. You can't convert NSDate to an "Indian" date.
You use calendars and timezones to convert NSDates to strings that you display to a user, in the way your users expect it. That's what you have done. You got a string that makes sense to Indian users. If an Indian user types a time, you take that string and convert it to an NSDate. The NSDate will be in Universal time. If you and I both typed in the time on our watch right now and converted it, you would type a time that looks like 5 1/2 hours earlier than mine. But it's the same time. If you convert it to NSDate, we will both get the exact same NSDate.
So how do you change your NSDate? Quite simple: You don't. NSDate is absolute time, independent of your location on earth.
Upon further Googling, I came across this post. The method described in it does exactly what I want. The original code is in Objective-C and since my question is in Swift, I'm going to post its Swift translation. \
func toLocalTime() -> NSDate {
let timeZone = NSTimeZone.localTimeZone()
let seconds = timeZone.secondsFromGMTForDate(self)
return NSDate(timeInterval: Double(seconds), sinceDate: self)
}
I added these as extension methods of NSDate so you can simply call them like this.
NSDate.date().toLocalTime()
You can compare two dates using any of the following NSDate functions: compare, earlierDate, laterDate, isEqualToDate. You should not compare date strings (oh, goodness, no, think of the nightmare); convert 'date strings' into 'NSDate' as soon as inputed.
In order to compare two dates that arose from strings correctly, you'll need the date strings to be unambiguous. In practice, that requires the date to have a time zone attached. If your server isn't providing a time zone and can't be modified to provide one, then you'll be forced to assume one (which would typically be the time zone where the server is located, assuming one server).
So, i'm trying to create a NSDate object for sunrise and sunset. I get the date based on NSDatePicker, i get coordinates from a Map, and i get the timezone from the GPS from the map.
I use this code to get the NSDate object: https://github.com/MosheBerman/KosherCocoa-legacy
This one to get the coordinates: https://github.com/digdog/MapKitDragAndDrop
And this one to get the the timezone based on coordinates: https://github.com/Alterplay/APTimeZones.
Right now my physical location is in Los Angeles, and the sunrise and sunset i'm using to testing is back home in Denmark.
-(NSString *)sunriseDate{
//Create the GeoLocation based on 'latitude' and 'longitude' (getting the from MapKitDragAndDrop) and 'location.timeZone' (getting that from APTimeZones).
GeoLocation *position = [[GeoLocation alloc] initWithName:#"position" andLatitude:latitude andLongitude:longitude andTimeZone:location.timeZone];
AstronomicalCalendar *astronomicalCalender = [[AstronomicalCalendar alloc] initWithLocation:position];
//daysBetween is the value from NSDatePicker
astronomicalCalender.workingDate = [NSDate dateWithTimeIntervalSinceNow:kSecondsInADay*[self daysBetween]];
NSDate *sunriseDate = [astronomicalCalender sunrise];
NSLog(#"Sunrise time: %#", sunriseDate);
//This spits out: Sunrise time: 2014-03-05 06:09:53 AM +0000 which is the right time.
NSDateFormatter *sunriseTime = [[NSDateFormatter alloc] init];
[sunriseTime setDateFormat:#"HH:mm:ss"];
NSString *sunriseString = [sunriseTime stringFromDate:sunriseDate];
NSLog(#"Sunrisestring: %#", sunriseString);
//This spits out: 10:09:53 PM.
return sunriseString;
}
Why does this happen and can anyone maybe give me a solution to this?
To anyone who might stumble into the same thing.
I found a library on github https://github.com/Alterplay/APTimeZones that helped me determine the timezone based on the coordinates.
Then i used
[sunriseTime setTimeZone:location.timeZone];
This put out the right time for the timezone.
Hope this helps anyone!
You need to match the input format correctly.
You may only be interested in the time but the NSDateFormatter doesn't care. NSDate is never JUST a time. It is a point in time and so includes the date too. It doesn't work without the date and time sections.
Also, this is probably one of THE MOST ASKED questions on Stack Overflow. Any other NSDate to NSString (or vice versa) question will answer this.
Your date format should be...
#"YYYY-MM-dd hh:mm:ss a EEEE"
I believe. Something like that anyway.
This spits out: 10:09:53 PM. This is correct local time for your time zone, which differs by 8 hours from Greenwich time Sunrise time: 2014-03-05 06:09:53 AM +0000. That's all. You have evening when a german man wakes up.
As Fogmeister said, you should include the timezone when creating a NSDateFormatter. Take a loot at Apple's Docs, Data Formatting Guide:
Fixed Formats
To specify a custom fixed format for a date formatter, you use setDateFormat:. The format string uses the format patterns from the Unicode Technical Standard #35.
The Unicode official site:
http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns
You may try using this: [sunriseTime setDateFormat:#"yyyy-MM-dd hh:mm:ss a EEEE"];
instead of [sunriseTime setDateFormat:#"HH:mm:ss"];
I am initializing an AFJSONRequestOperation (using the AFNetworking libraries) with a request that contains date fields. When the endpoint receives the request, the date is formatted in the region of the device. For example:
"last_update" = "dom dic 1 10:57:52 -0500 2013";
I would like to force the formatting to a region such as Canada or the US.
Is this possible as our endpoint is choking on dates that are not formatted with English such as:
"last_update" = "Wed Dec 1 10:57:52 -0500 2013";
If your API requires this, check out NSDateFormatter, which creates string representations of NSDate objects in any way you want. Just set the locale like this:
NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
[dateFormatter setLocale:usLocale];
Here's a good intro to this class at NSHipster.
You may find it simpler, though, to change your API to accept the number of seconds since 1 January 1970, GMT as the date. This is a common way to express date and time when transferring data between platforms. You can call the timeIntervalSince1970 method on your NSDate object to retrieve this data. Then the API can translate it to a locale, or a time zone, if it needs to.