Date to milliseconds and back to date in Swift

137,032

Solution 1

I don't understand why you're doing anything with strings...

extension Date {
    var millisecondsSince1970:Int64 {
        Int64((self.timeIntervalSince1970 * 1000.0).rounded())
    }
    
    init(milliseconds:Int64) {
        self = Date(timeIntervalSince1970: TimeInterval(milliseconds) / 1000)
    }
}


Date().millisecondsSince1970 // 1476889390939
Date(milliseconds: 0) // "Dec 31, 1969, 4:00 PM" (PDT variant of 1970 UTC)

Solution 2

As @Travis Solution works but in some cases

var millisecondsSince1970:Int WILL CAUSE CRASH APPLICATION ,

with error

Double value cannot be converted to Int because the result would be greater than Int.max if it occurs Please update your answer with Int64

Here is Updated Answer

extension Date {
 var millisecondsSince1970:Int64 {
        return Int64((self.timeIntervalSince1970 * 1000.0).rounded()) 
        //RESOLVED CRASH HERE
    }

    init(milliseconds:Int) {
        self = Date(timeIntervalSince1970: TimeInterval(milliseconds / 1000))
    }
}

About Int definitions.

On 32-bit platforms, Int is the same size as Int32, and on 64-bit platforms, Int is the same size as Int64.

Generally, I encounter this problem in iPhone 5, which runs in 32-bit env. New devices run 64-bit env now. Their Int will be Int64.

Hope it is helpful to someone who also has same problem

Solution 3

@Travis solution is right, but it loses milliseconds when a Date is generated. I have added a line to include the milliseconds into the date:

If you don't need this precision, use the Travis solution because it will be faster.

extension Date {

    func toMillis() -> Int64! {
        return Int64(self.timeIntervalSince1970 * 1000)
    }

    init(millis: Int64) {
        self = Date(timeIntervalSince1970: TimeInterval(millis / 1000))
        self.addTimeInterval(TimeInterval(Double(millis % 1000) / 1000 ))
    }

}

Solution 4

//Date to milliseconds
func currentTimeInMiliseconds() -> Int {
    let currentDate = Date()
    let since1970 = currentDate.timeIntervalSince1970
    return Int(since1970 * 1000)
}

//Milliseconds to date
extension Int {
    func dateFromMilliseconds() -> Date {
        return Date(timeIntervalSince1970: TimeInterval(self)/1000)
    }
}

I removed seemingly useless conversion via string and all those random !.

Solution 5

let dateTimeStamp = NSDate(timeIntervalSince1970:Double(currentTimeInMiliseconds())/1000)  //UTC time  //YOUR currentTimeInMiliseconds METHOD
let dateFormatter = NSDateFormatter()
dateFormatter.timeZone = NSTimeZone.localTimeZone() 
dateFormatter.dateFormat = "yyyy-MM-dd"
dateFormatter.dateStyle = NSDateFormatterStyle.FullStyle
dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle


let strDateSelect = dateFormatter.stringFromDate(dateTimeStamp)
print("Local Time", strDateSelect) //Local time


let dateFormatter2 = NSDateFormatter()
dateFormatter2.timeZone = NSTimeZone(name: "UTC") as NSTimeZone!
dateFormatter2.dateFormat = "yyyy-MM-dd"

let date3 = dateFormatter.dateFromString(strDateSelect)
print("DATE",date3)
Share:
137,032

Related videos on Youtube

user1079052
Author by

user1079052

Updated on November 12, 2021

Comments

  • user1079052
    user1079052 over 2 years

    I am taking the current time, in UTC, and putting it in nanaoseconds and then I need to take the nanoseconds and go back to a date in local time. I am able to do get the time to nanoseconds and then back to a date string but the time gets convoluted when I go from a string to date.

        //Date to milliseconds
         func currentTimeInMiliseconds() -> Int! {
                let currentDate = NSDate()
                let dateFormatter = DateFormatter()
                dateFormatter.dateFormat = format
                dateFormatter.timeZone = NSTimeZone(name: "UTC") as TimeZone!
                let date = dateFormatter.date(from: dateFormatter.string(from: currentDate as Date))
                let nowDouble = date!.timeIntervalSince1970
                return Int(nowDouble*1000)
            }
    
        //Milliseconds to date
        extension Int {
            func dateFromMilliseconds(format:String) -> Date {
                let date : NSDate! = NSDate(timeIntervalSince1970:Double(self) / 1000.0)
                let dateFormatter = DateFormatter()
                dateFormatter.dateFormat = format
                dateFormatter.timeZone = TimeZone.current
                let timeStamp = dateFormatter.string(from: date as Date)
    
    let formatter = DateFormatter()
                formatter.dateFormat = format
                return ( formatter.date( from: timeStamp ) )!
            }
        }
    

    //The timestamp is correct but the date returned isn't

    • vadian
      vadian over 7 years
      What is the purpose of converting a date to string and right back to date (in currentTimeInMiliseconds())?
    • user1079052
      user1079052 over 7 years
      The company I work for stores all dates in milliseconds
    • vadian
      vadian over 7 years
      But what the is double conversion date -> string -> date for and what is the given format which is missing in the code?
    • user1079052
      user1079052 over 7 years
      I don't understand what you are trying to say. I use currentTimeToMilliseconds to send UTC dates to the server. Then I use dateFromMilliseconds to go back to a current date when the server sends times.
    • vadian
      vadian over 7 years
      You are converting a date to a string and right back to the same date which seems to be useless. Once again, what is the used date format format? Actually Int(Date().timeIntervalSince1970 * 1000) can replace the entire function. NSDate is just a double value without considering a time zone
    • Caleb
      Caleb over 5 years
      You seem to use nanoseconds in your question when you appear to mean milliseconds. There are 1 million nanoseconds in a millisecond, so it's not an inconsequential mistake.
  • user1079052
    user1079052 over 7 years
    This would be great but I need currentTimeInMilliseconds to convert the local time to UTC and I need dateFromMilliseconds to convert from UTC to local time
  • user28434'mstep
    user28434'mstep over 7 years
    Timestamp is in UTC already.. > The number of seconds from the reference date (00:00:00 **UTC** on 1 January 1970)
  • user1079052
    user1079052 over 7 years
    I am doing the string because i need millisecondsSince1970 to be in UTC and init(milliseconds:Int) to be put back in local time.
  • Travis Griggs
    Travis Griggs over 7 years
    Date objects are always in UTC. Those values in my example are UTC (note how the description method then renders the UTC epoch beginning in PDT).
  • dickyj
    dickyj about 7 years
    Better to do init(milliseconds:Double) instead of Int or else you will lose the milliseconds when you convert back.
  • davis
    davis almost 7 years
    doesn't this solution lose the millisecond precision?
  • DoesData
    DoesData over 6 years
    Why would that error happen? Time interval since 1970 is a 32 bit number. At least until we get to this: en.wikipedia.org/wiki/Year_2038_problem
  • Prashant Tukadiya
    Prashant Tukadiya over 6 years
    @DoesData If you see we are multiplying number with 1000. this causes out of the range of Int32
  • Nicolas Guillaume
    Nicolas Guillaume about 6 years
    davis: If I understand correctly, the timeIntervalSince1970 is a double and therefore has millisecond precision in it. The multiplier and cast are there to convert this into a int.
  • AechoLiu
    AechoLiu over 5 years
    Some old iOS device run in 32-bit env. It's Int is Int32. But new iOS device, ex: iPhone 6, it's Int is Int64. So, 32-bit problem may cause crash in old iOS devices.
  • Prashant Tukadiya
    Prashant Tukadiya over 5 years
    @AechoLiu Thanks for pointing it what should be solution for this case ? Can you help me to update my answer
  • doogilasovich
    doogilasovich over 5 years
    I ran into this issue on 32-bit systems (iPad 2) as well. This should be the correct answer.
  • WestCoastProjects
    WestCoastProjects almost 4 years
    Date().millisecondsSince1970 is showing as unresolved
  • famfamfam
    famfamfam almost 4 years
    why should * 1000, i think we lost the milisecond
  • Jase
    Jase almost 4 years
    @javadba try Date().timeIntervalSince1970. The return value is a Double that represents the number of seconds since 1970 – it is precise to 'sub-millisecond precision'. See here: developer.apple.com/documentation/foundation/timeinterval
  • WestCoastProjects
    WestCoastProjects almost 4 years
    @Jase Thx yes I did finally run into that soon after and it works.
  • Peter Schorn
    Peter Schorn over 3 years
    @javadba Date().millisecondsSince1970 is a custom extension in the posts for this question. It's not in Foundation.
  • Peter Schorn
    Peter Schorn over 3 years
    @davis It doesn't loose the millisecond precision, but it does loose sub-millisecond precision. Unless you absolutely need to convert the date to an integer, consider using my answer.
  • Peter Schorn
    Peter Schorn over 3 years
    You will not lose millisecond precision, but you will lose sub-millisecond precision. Unless the time interval absolutely needs to be represented as an integer, consider my answer below instead.
  • user28434'mstep
    user28434'mstep over 3 years
    @PeterSchorn, yep, this code in the answer was just a cleaned up version of the code from the question. The question had Int, therefore the answer has Int too.
  • Peter Schorn
    Peter Schorn over 3 years
    @user28434 Ok, got it. Hopefully other people will find my answer userful though.