3

Is there a way to get a server time to use with swift. I want to set a static time based on a server. so that even if a user changes the time zone and the date, it wouldn't matter and the time which will show on the view controller will be a time based on the server rather than the NSDate

 let today = NSDate()
 println(today)

at present the above code, changes the date and time if its altered in the phone settings. i am also using parse in my code. is there a way to get the server time from parse.

  • Why not just set the `NSDate`'s timezone to the same as the server you want to use, therefore no network call? http://stackoverflow.com/a/24917928/1186243 – sbarow Jul 13 '15 at 10:35
  • the timezone function is fine based on the link. how do you set the date to the server is what i would like to know. cause at the moment when i change the date setting on my phone to a past or future date, the date changes in the app :) – Mugunthan Balakrishnan Jul 13 '15 at 11:10
  • Have a look at this https://www.parse.com/questions/is-there-a-way-to-retrieve-the-current-server-time – sbarow Jul 13 '15 at 11:17
  • think that code is javascript based – Mugunthan Balakrishnan Jul 13 '15 at 11:26
  • 1
    Compare http://stackoverflow.com/questions/9075303/get-date-and-time-from-apple-server. – Martin R Jul 13 '15 at 11:36
  • @MugunthanBalakrishnan that code is Javascript, because you mentioned you want to use Parse, so you would use Parse's cloud code which is written in Javascript. I would suggest using Martin R's link if you just want to call a service that already exists. – sbarow Jul 13 '15 at 11:40
  • thanks guys, will try and work around the link martin has suggested – Mugunthan Balakrishnan Jul 13 '15 at 11:44
  • https://github.com/freak4pc/NSDate-ServerDate i came across this example, its written in Objective-C. tried it and it works . should be able to convert it to swift. – Mugunthan Balakrishnan Jul 13 '15 at 11:53

3 Answers3

7

Based on this link https://github.com/freak4pc/NSDate-ServerDate i wrote the code for swift. Tried and tested. And it works.

override func viewDidLoad() {
    super.viewDidLoad()

    //call ServerTimeReturn function

    serverTimeReturn { (getResDate) -> Void in
        var dFormatter = NSDateFormatter()
        dFormatter.dateStyle = NSDateFormatterStyle.LongStyle
        dFormatter.timeStyle = NSDateFormatterStyle.LongStyle
        dFormatter.timeZone = NSTimeZone(abbreviation: "GMT")
        var dateGet = dFormatter.stringFromDate(getResDate)

        println("Formatted Time : \(dateGet)")
    }

        }

    func serverTimeReturn(completionHandler:(getResDate: NSDate!) -> Void){

    let url = NSURL(string: "http://www.google.com")      
    let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
        let httpResponse = response as? NSHTTPURLResponse
        if let contentType = httpResponse!.allHeaderFields["Date"] as? String {

            var dFormatter = NSDateFormatter()
            dFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss z"
            var serverTime = dFormatter.dateFromString(contentType)
            completionHandler(getResDate: serverTime)
        }
    }

    task.resume()
}
4

You shouldn't make the same network call every time you need to get corrected datetime.

So I would do like below, so I can call setSeverDate() only when I need to correct datetime:

var serverDate = Date() {
    didSet {
        let possibleNow = Date()
        gap = possibleNow.distance(to: serverDate)
    }
}
var gap: TimeInterval = 0
var correctedDate: Date {
    let possibleNow = Date()

    //Ignores network delay time same with or less than 2 seconds
    let now = abs(gap) > 2 ? possibleNow.advanced(by: gap) : possibleNow

    //For Debugging
    print("\(possibleNow) + \(gap) = \(now)")

    return now
}

func setServerDate() {
    let url = URL(string: "https://www.google.com")

    URLSession.shared.dataTask(with: url!) { _, response, _ in
        let httpResponse = response as? HTTPURLResponse
        if let contentType = httpResponse!.allHeaderFields["Date"] as? String {
            let formatter = DateFormatter()
            formatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss z"
            formatter.timeZone = TimeZone.current
            serverDate = formatter.date(from: contentType) ?? Date()
        } else {
            print("getting google server date failed")
            serverDate = Date()
        }
    }.resume()
}
eastriver lee
  • 55
  • 1
  • 8
3
  func getServerTimer(completion:@escaping (Date?)->()) {

    serverTimeReturn { date   -> Void in
        let dFormatter = DateFormatter()
        dFormatter.dateStyle = .long
        dFormatter.timeStyle = .long
        dFormatter.timeZone = TimeZone(abbreviation: "GMT")
        if let date = date {
            let dateGet = dFormatter.string(from: date)
            completion(date)
            print("Formatted Time : \(dateGet)")
        } else {
            completion(nil)
        }
    }

}

func serverTimeReturn(completionHandler:@escaping (_ getResDate: Date?) -> Void) {

    let url = NSURL(string: "https://www.google.com")
    let task = URLSession.shared.dataTask(with: url! as URL) {(data, response, error) in
        let httpResponse = response as? HTTPURLResponse
        if let contentType = httpResponse!.allHeaderFields["Date"] as? String {

            let dFormatter = DateFormatter()
            dFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss z"
            dFormatter.locale = Locale(identifier: "en-US")
            if let serverTime = dFormatter.date(from: contentType) {
                completionHandler(serverTime)
            } else {
                completionHandler(nil)
            }
        }
    }

    task.resume()
}
Masoud Rahimi
  • 5,449
  • 14
  • 36
  • 62
Chris
  • 6,342
  • 3
  • 15
  • 34