开发者

Auto-renewable subscription receipt date format

I'm struggling to figure out the formatting for the following date:

2011-05-24 19:02:32 Etc/GMT

This date is returned from Apple's receipt validation service and开发者_开发百科 I need to turn it into a NSDate for some comparison operations. The real trouble is related to the timezone.

Here's some code I've already written:

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

        NSDateFormatter *f = [[NSDateFormatter alloc] init];

        [f setLocale:[NSLocale currentLocale]];
        [f setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
        [f setDateFormat:@"yyyy-MM-dd HH:mm:ss vvvv"];

        NSLog(@"%@", [f stringFromDate:[NSDate date]]);

        NSDate *subPurchaseDate = [f dateFromString:[receiptData valueForKey:@"original_purchase_date"]];

        [f release];

I've tried all combinations of 'v's and 'Z's that I can think of. Any insight?


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+.


This is what I do on Swift 3 to convert the date from an auto-renewable date from a receipt.

let expirationDate = "2017-08-16 23:10:35 Etc/GMT"
let receiptDateFormat = "yyyy-MM-dd HH:mm:ss VV"
let theDateFormat = DateFormatter.Style.medium
let theTimeFormat = DateFormatter.Style.medium
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = receiptDateFormat
let firstDate = dateFormatter.date(from: stringDate)
dateFormatter.dateStyle = theDateFormat
dateFormatter.timeStyle = theTimeFormat

let result = dateFormatter.string(from: firstDate!)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜