Auto-renewable subscription receipt date format

By looking at the date format documentation I got the correct format, is works well for me:

        NSDateFormatter * formatter = [NSDateFormatter new];
        formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss VV";

        NSDate * purchaseDate = [formatter dateFromString:latestTransaction[@"original_purchase_date"]];
        NSDate * expirationDate = [formatter dateFromString:latestTransaction[@"expires_date"]];

No need to set the time zone on the formatter since it's embedded in the string.
Manipulating the date string to parse it is not a good idea.

Source: http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns


After doing some more research, the code I'm using here works, but is suspect;

   NSString *purchaseDateString = [@"2011-05-24 19:02:32 Etc/GMT" stringByReplacingOccurrencesOfString:@" Etc/GMT" withString:@""];
   NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
   NSLocale *POSIXLocale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"] autorelease];
   [formatter setLocale:POSIXLocale];
   [formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
   [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

   NSDate *purchaseDate = [formatter dateFromString:purchaseDateString];

I don't like the assumptions I am making about the incoming date string and so I am assuming this code may break for other stores (I'm testing against the UK one). So although this kind of works for my own situation, I'd really like to see a more robust solution that actually parses the timezone string correctly as per the original question.

I can't quite believe Apple have used a deprecated timezone (all the Etc/* ones are officially deprecated) in these important date strings!

EDIT:

I note you are using

NSDictionary *receiptData = [info valueForKey:@"expires_date"];

This is not actually a string according to the documentation it should be "The expiration date of the subscription receipt, expressed as the number of milliseconds since January 1, 1970, 00:00:00 GMT"

However the question is still valid as you have to use the purchase_date field when working with restored subscriptions and this field is in the text format you have described.


The following code can be used to parse RFC 3339 dates found in App Store receipts:

let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss VV"
formatter.timeZone = TimeZone(secondsFromGMT: 0)

let date = formatter.date(from: "2020-06-17 10:59:33 Etc/GMT")

Note that it is necessary to set the timeZone as well as the locale. Also setting locale before dateFormat is important according to Technical Q&A QA1480.

Apple recommends using the newer ISO8601DateFormatter API on iOS 10+ and macOS 10.12+.