Receipt dates - timezone?

Hello,


I want to compare the dates of in-app purchases, and would like to know if the OriginalPurchaseDate is always in UTC timezone?

Decoding the receipt on device, the date is in RFC3339 format, a format which allows for a timezone offset of +HH:MM or -HH:MM but all the receipts I have seen use the "Z" format which indicated timezone is UTC. Is it safe to assume all dates in the OriginalPurchaseDate field will be UTC timezone ?


On Device Receipt


CancelDate = "";
OriginalPurchaseDate = "2017-01-03T13:07:31Z";
OriginalTransactionIdentifier = 1000000262542087;
ProductIdentifier = "com.mycompany.app.sub.1month";
PurchaseDate = "2017-01-03T13:07:29Z";
Quantity = 1;
SubExpDate = "2017-01-03T13:12:29Z";
TransactionIdentifier = 100000262542087;
WebItemId = 18446744072207895811;


Server Validated Receipt

For server validated receipts the response we get from Apple, includes extra useful fields, like the original_purchase_date_ms which gives the date as an UTC epoch time in millisenconds. Is this field supported ? It's not in the receipt fields documentation that I am aware of.


[quantity] => 1                   
[product_id] => com.sparkleapps.puzzlepack.landmarks3                      
[transaction_id] => 20000192364074
[original_transaction_id] => 20000192364074
[purchase_date] => 2015-06-10 22:27:30 Etc/GMT
[purchase_date_ms] => 1433975250000
[purchase_date_pst] => 2015-06-10 15:27:30 America/Los_Angeles
[original_purchase_date] => 2015-06-10 22:27:30 Etc/GMT
[original_purchase_date_ms] => 1433975250000
[original_purchase_date_pst] => 2015-06-10 15:27:30 America/Los_Angeles
[is_trial_period] => false



Many Thanks

You can't rely on undocumented fields. Here is a formatter that works on the dates:

    formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];
    [formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];

That format doesn't work, since it doesn't handle the long time zone strings like "America/Los_Angeles" or "Etc/GMT".


The documentation at https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html#//apple_ref/doc/uid/TP40010573-CH106-SW12 says that dates are in the RFC 3339 date format, but it is incorrect. Hence the standard NSISO8601DateFormatter formatter cannot be used, at least without manually massaging the time zone in the string.

The only format string I've found that can parse it is: "yyyy-MM-dd HH:mm:ss VV"

But what to do if Apple decides to correct the error and start sending time zones that are correctly formatted? Probably the best bet is to fallback on an NSISO8601DateFormatter if the above formatting string fails.


Alarmingly, everyone (incuding popular frameworks like SwiftyStoreKit) seems to be just relying on the undocumented "_ms" fields instead (e.g., "creation_date_ms" rather than "creation_date"), but at this point they are probably safe since their removal would break thousands of apps' receipt validation code.

Like a formater I parse the original question a bit differently from you. The date formater I suggest works on the fields decoded on the device using OpenSSL. You are correct - you need to chop of that end piece if you are sending the receipt to the Apple servers for decoding. I'd simply use [theString substringToIndex:19] and not worry about it.

Right, the local ASN.1 fields are correctly in RFC3339 format, so you could just use the ISO8601DateFormatter to parse them.


The server-returned fields are however in a non-ISO8601/RFC3339 format, so my format string should work on them, or you can just manually chop off the end of the string. Both solutions run the risk of breaking if Apple updates their servers to return the dates in the format that they document they should return.

Receipt dates - timezone?
 
 
Q