3

I am trying to convert date from apple receipt to swift global date and time. But I am not succeeded,

Purchased time (device): 2019-08-30 22:23:44 America/Los_Angeles

Purchased time (server): 2019-08-31 05:23:44 Etc/GMT

Expire time (server): 2019-08-31 05:28:44 Etc/GMT

When I get date by using Date(), it's completely or almost some hour difference than my device & those date&time above. I wanted to compare today Date() into expire time.

I used below codes but not success,

extension Date {
    static func fromAppleServer(dateString: String) -> Date? {
        let seperated = dateString.components(separatedBy: " ")
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        dateFormatter.timeZone = TimeZone(identifier: seperated.last!)
        let dateObject = dateFormatter.date(from: (seperated.dropLast()).joined(separator: " "))
        return dateObject
    }
    static func localUTC() -> Date {
        let date = Date()
        print("Date before conversion: \(date)")
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        let string = dateFormatter.string(from: date)
        dateFormatter.timeZone = TimeZone(identifier: "America/Los_Angeles")
        return dateFormatter.date(from: string)!
    }
}

let appleDate = Date.fromAppleServer(dateString: "2019-08-30 22:29:02 America/Los_Angeles") //used  2019-08-31 05:23:44 Etc/GMT too
let localUTC = Date.localUTC()

print("Apple Server: ",appleDate) //Always 2019-08-31 05:29:02 +0000
print("Local UTC: ",localUTC)

Update:

Tried code:

extension Date{

    static func fromAppleServer(dateString: String) -> Date?{

        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss VV"
        dateFormatter.timeZone = TimeZone(identifier: "UTC")
        let dateObject = dateFormatter.date(from: dateString)
        return dateObject
    }

    static func localUTC() -> Date{

        let date = Date()
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss VV"
        let string = dateFormatter.string(from: date)
        dateFormatter.timeZone = TimeZone(identifier: "UTC")
        return dateFormatter.date(from: string)!
    }
}

Debugging Log:

(lldb) po print date
    ▿ 2019-08-31 05:28:44 +0000
- timeIntervalSinceReferenceDate : 588922124.0

Fix-it applied, fixed expression was:
print; date
(lldb) po print Date.localUTC()
▿ 2019-09-01 03:07:45 +0000
- timeIntervalSinceReferenceDate : 589000065.0

Fix-it applied, fixed expression was:
print; Date.localUTC()
(lldb) po print self.expiryDate
▿ Optional<String>
- some : "2019-08-31 05:28:44 Etc/GMT"

Fix-it applied, fixed expression was:
print; self.expiryDate
(lldb) po print Date()
▿ 2019-09-01 03:09:03 +0000
- timeIntervalSinceReferenceDate : 589000143.939402

Fix-it applied, fixed expression was:
print; Date()
(lldb)

Here,

Device date is ~ 8:mm PM, Sat 31 August. Purchased date is(5 mins duration):2019-08-31 05:23:44 Etc/GMT (For device it's 8:mm PM Sat 31 August) Expire date is: 2019-08-31 05:28:44 Etc/GMT Swift Date is:~ 2019-09-01 03:09:03

I thought we can easily compare date once Etc/GMT time is converted into Swift Date() global time. But I can't convert 2019-08-31 05:28:44 Etc/GMT to ~ 2019-09-01 03:09:03. So, how to convert it? or Any other suggestions welcome.

Note: '~' indicates some seconds or minutes delay because of testing time.

  • What is `Etc/GMT`? – rmaddy Sep 01 '19 at 02:01
  • it is probably UTC – Leo Dabus Sep 01 '19 at 02:08
  • @rmaddy, I don't know what is Etc/GMT. Just got in apple receipt json objects. –  Sep 01 '19 at 02:45
  • @LeoDabus, okay I will convert local time into UTC –  Sep 01 '19 at 02:46
  • @LeoDabus, Just wanted to convert `etc/GMT` time to global time like Swift `Date()`. –  Sep 01 '19 at 03:14
  • @Aishu check my post how to parse all your date strings. – Leo Dabus Sep 01 '19 at 03:15
  • What is global time? Do you mean local time? – Leo Dabus Sep 01 '19 at 03:19
  • Swift `Date()` gives same time anywhere in this earth. Sorry, I don't know the name, So I called it global time (thought seen some where). I will add updated code and debugger log in question –  Sep 01 '19 at 03:24
  • To properly parse your string (convert it to a Date object) you need to interprete the timezone as I suggested in my post – Leo Dabus Sep 01 '19 at 03:25
  • print will always display the UTC time representation of the date object (zero seconds from GMT same as +0000). If you need to display that date to the user you need to use date formatter (date and time style) to respect the user locale and device settings. – Leo Dabus Sep 01 '19 at 03:27
  • this might help you understand timezones https://stackoverflow.com/a/28347285/2303865 – Leo Dabus Sep 01 '19 at 03:30
  • @LeoDabus, Okay thank you! I will try and let you know. Thank you so much! –  Sep 01 '19 at 03:36
  • @Aishu your localUTC() method doesn't make any sense. You don't need to do any time conversion. Date is just a point in time. The actual time description will vary depending of the user location. – Leo Dabus Sep 01 '19 at 03:44

1 Answers1

3

No need to manually parse your date string. You can use date format "VV" to interprete the timezone identifier associated with your date string:

extension Formatter {
    static let customDate: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss VV"
        return formatter
    }()
}

let dateString = "2019-08-31 05:23:44 Etc/GMT" // or "2019-08-30 22:23:44 America/Los_Angeles"
if let date = Formatter.customDate.date(from: dateString) {
    print(date)  // "2019-08-31 05:23:44 +0000\n"
    print(date.description(with: .current))  // "Saturday, August 31, 2019 at 2:28:44 AM Brasilia Standard Time\n"
}
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571