I am using a web services which returns a JSON WCF DateTime.
The string goes like \/Date(1316397792913+0800)\/
I am interested in extracting out the 1316397792 which is the time since 1st Jan 1970 in seconds. So that I can use the NSDate timeIntervalSince1970 method to get the present time. I cropped out the last 3 digits as it's in milliseconds and the timeIntervalSince1970 takes in seconds.
Here's what I am currently doing which does not work for dates somewhere before 2001 which has a time interval in ms since 1970 less than 10 characters.
NSString *dateString = #"\/Date(1316397792913+0800)\/";
NSLog(#"dateString :%#", dateString);
NSDate *date = [NSDate dateWithTimeIntervalSince1970:
[[dateString substringWithRange:NSMakeRange(6, 10)] intValue]];
NSLog(#"NSDate:%#", date);
dateString :/Date(1316397792913+0800)/
NSDate:2011-09-19 02:03:12 +0000
Therefore, I need a better work around playing with the dateString which does not assume everytime we will be feteching 10 characters.
You can simply get the substring between the index of ( and the index of +. Something like:
NSRange begin = [dateString rangeOfString:"("];
NSRange end = [dateString rangeOfString:"+"];
NSString* milliSecondsSince1970 = [dateString substringWithRange:NSMakeRange(begin.location + 1, end.location - begin.location - 1)];
P.S: Check for the one off error.
Related
Below is the string of time stamp which is returned by some server
dateFromServer = 2013-07-08 16:45:03Z
I am doing the following to convert it to an NSDate
NSDateFormatter *format = [[NSDateFormatter alloc] init];
[format setDateFormat:#"yyyy'-'MM'-'dd' 'HH':'mm':'ss'Z'"];
NSTimeZone *destinationTimeZone = [NSTimeZone systemTimeZone];
[format setTimeZone:destinationTimeZone];
dateFromServer = [dateFromServer stringByReplacingOccurrencesOfString:#"T" withString:#" "];
NSDate *oldTime = [format dateFromString:dateFromServer];
and I am getting
oldTime is 2013-07-08 20:45:03 +0000
It looks like +4 is added to the original time stamp
Why does it do that, and how do I avoid this situation?
The NSDate object doesn't preserve the timezone. Instead, when printing the date (I assume through a NSLog(#"%#", oldTime);) it will use the current timezone. If your system is set to GMT (+0000) then it will print like that.
The date is still correct, and if you force it to print with the correct time zone it will be correct.
I personally do not know objective C but I do know the point of the problem. I'll try to guess along with the syntax.
When you receive 2013-07-08 16:45:03Z the Z means UTC, or GMT+/-0000.
You are parsing it as a local timezone, or GMT-0400.
You then reemit it as reconverted into UTC with a 4 hour overcompensation.
To fix this, change:
NSTimeZone *destinationTimeZone = [NSTimeZone systemTimeZone];
to
NSTimeZone *destinationTimeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
Honestly, I'm not sure if you need to do any wrapping for the 0 to act as an NSInteger but that's what you need.
You may have been intermittently missing this bug as a failure to determine time would have fallen back to the desired effect.
Out of curiosity, could someone comment as to whether my code is at least partially correct?
This question already has answers here:
How to convert NSDate into unix timestamp iphone sdk?
(10 answers)
Closed 9 years ago.
I have a date like this 01/20/2013 and trying to get the unix timestamp for this date. I have searched a lot and found out that how to convert present date into unix timestamp but didn't find my solution.
here is my code what i'm doing.
NSDate *date = mydate; //myDate is the date like 01/20/2013
NSDateFormatter *formatter = [[ NSDateFormatter alloc]init];
[formatter setDateFormat:#"mm/dd/yyyy"];
NSString *timestamp = [formatter stringFromDate:date];
NSLog(#"%#",timestamp);
I'm getting null as timestamp value in my console.
iOS provides -(NSTimeInterval)timeIntervalSince1970 for NSDate objects which returns the number of seconds since 00:00:00 GMT January 1, 1970. NSTimeInterval is a double floating point type so you get the seconds and fractions of a second.
time_t unixTime = (time_t) [your_date timeIntervalSince1970];
Here time_t is usually a signed 32-bit integer type (long or int).
you can get it with
- (NSTimeInterval)timeIntervalSince1970
UPDATE:
For Example in int ...
int unixtimestamp = [mydate timeIntervalSince1970];
And other Example in NSTimeInterval
NSTimeInterval ti = [mydate timeIntervalSince1970];
I get a unix timestamp from the database and I am trying to create a human readable date from it. I am using this way
long t1=[time longLongValue];
NSDate* date=[NSDate dateWithTimeIntervalSince1970:t1];
where time is the timestamp. When I print date I get
1956-02-18 19:04:01 +0000
instead of
2013-01-02 12:31:03 +0000
The timestamp was 1356765933449
It is a matter of integer overflow, as Boris correctly pointed out in his answer.
I don't know what your time object is, but instead of a signed long int use a NSTimeInterval.
On iOS NSTimeInterval is currently defined as
typedef double NSTimeInterval;
but you shouldn't care too much about that. Sticking with type synonyms will protect you in case Apple decides to change the underlying definition to something else.
That said you should change your code to something like
NSTimeInterval epoch = [time doubleValue];
NSDate * date = [NSDate dateWithTimeIntervalSince1970:epoch];
Concerning the code maintainability issue I described before, here you are explicitly using a doubleValue (you don't have many options), but the good thing is that if Apple changes the NSTimeInterval definition to something not compatible with a double assignment, the compiler will let you know.
Try this
- (NSString *) getDateFromUnixFormat:(NSString *)unixFormat
{
NSDate *date = [NSDate dateWithTimeIntervalSince1970:[unixFormat intValue]];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"MMM dd, yyyy-h:mm"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
//NSDate *date = [dateFormatter dateFromString:publicationDate];
NSString *dte=[dateFormatter stringFromDate:date];
[dateFormatter release];
return dte;
}
The Unix timestamp has only 32 Bits available.
Because they use a signed int, they count the seconds from 1.1.1970. A 32 Bit signed int can only hold values up to 2147483647, where as you want it to be 1356765933449. That causes an overflow, and that causes your date to be invalid.
This is also known as the Year 2038 Problem, because 2147483647 (max value) will be hit on 03:14:07 UTC on Tuesday, 19 January 2038.
Then format the date using nsdateformatter. Details guide.
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSDateFormatter_Class/Reference/Reference.html
I have a TimeZone as NSString value given as "GMT-09:00".
All I want is to setup my NSTimeZone with this format. I tried but wasn't able to do this. This time may vary every time so i can't set it as static in the method
eg. i can't do this -- timeZoneForSecondsFromGMT:(-9*3600).
Also, can I convert the above format (GMT-09:00) into number of seconds anyhow??
EDIT : I just want to set the time zone to a specific GMT format. It could be anything, GMT-09:00, GMT+05:30, etc.
If it was a static value I could have used the below method for NSTimeZone.
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:(-9*3600)]];
But the value "GMT-09:00" is an NSString. So everytime, I would have to break the string and get the values for Hours and minutes. Is there an easier way?????
Thanks for the help!
have you tried something like this?
NSString *tzStr = #"GMT-09:00";
NSTimeZone *tz = [[NSTimeZone alloc] initWithName:tzStr];
NSLog(#"Tz: %#", tz);
NSLog(#"Offset: %d", [tz secondsFromGMT]);
// Tz: GMT-0900 (GMT-09:00) offset -32400
// Offset: -32400
works with #"GMT+5:30" too.
// Tz: GMT+0530 (GMT+05:30) offset 19800
and then just use [formatter setTimeZone:tz];
this one is helpful to you. optimized help
float offsetSecond = ([[NSTimeZone systemTimeZone] secondsFromGMT] / 3600.0);
I have the following code that is meant to convert milliseconds into hours, mins and seconds:
int hours = floor(rawtime / 3600000);
int mins = floor((rawtime % 3600000) / (1000 * 60));
int secs = floor(((rawtime % 3600000) % (1000 * 60)) / 1000);
NSLog(#"%d:%d:%d", hours, mins, secs);
NSString *hoursStr = [NSString stringWithFormat:#"%d", hours];
NSString *minsStr = [NSString stringWithFormat:#"%d", mins];
NSString *secsStr = [NSString stringWithFormat:#"%d", secs];
NSLog(#"%a:%a:%a", hoursStr, minsStr, secsStr);
Fairly straightforward. Rawtime is an int with value 1200. The output is like this:
0:0:1
0x1.3eaf003d9573p-962:0x1.7bd2003d3ebp-981:-0x1.26197p-698
Why is it that converting the ints to strings gives such wild numbers? I've tried using %i and %u and they made no difference. What is happening?
You have to use %# as the conversion specifier for an NSString. Change your last line to:
NSLog(#"%#:%#:%#", hoursStr, minsStr, secsStr);
%a means something totally different. From the printf() man page:
aA
The double argument is rounded and converted to hexadecimal notation in the style
[-]0xh.hhhp[+-]d
where the number of digits after the hexadecimal-point character is equal to the precision specification.
Instead of rolling your own string formatting code, you should be using an NSNumberFormatter for numbers or an NSDateFormatter for dates/times. These data formatters take care of localization of format to the user's locale and handle a variety of formats built-in.
For your use, you need to convert your millisecond time into an NSTimeInterval (typedef'd from a double):
NSTimeInterval time = rawtime/1e3;
Now you can use an NSDateFormatter to present the time:
NSDate *timeDate = [NSDate dateWithTimeIntervalSinceReferenceDate:time];
NSString *formattedTime = [NSDateFormatter localizedStringFromDate:timeDate
dateStyle:NSDateFormatterNoStyle
timeStyle:NSDateFormatterMediumStyle];
NSString *rawTime = [[formattedTime componentsSeparatedByString:#" "] objectAtIndex:0];
on OS X where the last line removes the "AM/PM". This will work for any time less than 12 hrs and will give a formatted string in the localized format for HH:MM:SS. On the iPhone, localizedStringFromDate:dateStyle:timeStyle: isn't available (yet). You can achieve the same effect with setTimeStyle:, setDateStyle: and stringFromDate: on a date formatter instance.