18

我正在努力弄清楚以下日期的格式:

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

此日期是从 Apple 的收据验证服务返回的,我需要将其转换为 NSDate 以进行一些比较操作。真正的麻烦与时区有关。

这是我已经编写的一些代码:

        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];

我已经尝试了所有我能想到的 'v's 和 'Z's 组合。有什么见解吗?

4

4 回答 4

16

通过查看日期格式文档,我得到了正确的格式,对我来说效果很好:

        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"]];

无需在格式化程序上设置时区,因为它嵌入在字符串中。
操纵日期字符串来解析它不是一个好主意。

资料来源:http ://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns

于 2014-06-06T23:04:18.637 回答
4

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.

于 2011-06-13T19:00:19.857 回答
1

以下代码可用于解析App Store 收据中的 RFC 3339 日期

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")

请注意,必要设置timeZone以及locale。根据技术问答 QA1480locale ,之前的设置也很重要。dateFormat

Apple 建议ISO8601DateFormatter在 iOS 10+ 和 macOS 10.12+ 上使用更新的API。

于 2020-05-23T10:59:39.300 回答
0

这就是我在 Swift 3 上所做的,将日期从收据的自动更新日期转换。

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!)
于 2017-08-17T23:45:27.090 回答