6

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

Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
zzzzz
  • 1,209
  • 2
  • 18
  • 45
  • 1
    read [this](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html) and [this](http://stackoverflow.com/questions/5739598/setting-date-format-for-nsdateformatter) – tkanzakic Jan 02 '13 at 11:43

4 Answers4

7

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.

Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
6

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;

}
Talha
  • 809
  • 4
  • 13
  • it is returning Jan 19, 2038-3:14 for messages which were sent today. – zzzzz Jan 02 '13 at 11:50
  • Ok I checked it with my method also if I use intValue in my method for your given timestamp it returns same result as you get but id I use doubleValue this is what I have got Mar 14, 44964-2:57, it seems that the timeStamp is way too large – Talha Jan 02 '13 at 12:12
  • also see [this thread](http://stackoverflow.com/questions/5827240/create-nsdate-from-unix-timestamp) I have tried the same still got that result – Talha Jan 02 '13 at 12:13
6

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.

Boris Prohaska
  • 912
  • 6
  • 16
0

Then format the date using nsdateformatter. Details guide.

https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSDateFormatter_Class/Reference/Reference.html

NSCry
  • 1,662
  • 6
  • 23
  • 39