mardi 4 août 2015

In Swift, how can I get an NSDate from a dispatch_time_t?

"Walltime" is a little-known time format used by Grand Central Dispatch. Apple talks about it here:

http://ift.tt/1HnSNLW

There are some things it's really handy for, though, but it's a sticky wicket. It's hard to make it play nice with other time formats, which is what my question's about.

I can make a walltime by turning an NSDate into a timespec, and then using with dispatch_walltime:

 let now = NSDate().timeIntervalSince1970
 let nowWholeSecsFloor = floor(now)
 let nowNanosOnly = now - nowWholeSecsFloor
 let nowNanosFloor = floor(nowNanosOnly * Double(NSEC_PER_SEC))
 var thisStruct = timespec(tv_sec: Int(nowWholeSecsFloor),
 tv_nsec: Int(nowNanosFloor))
 let wallTime = dispatch_walltime(& thisStruct, 0)

But lord love a duck, I can't figure out how to get it back into an NSDate. Here's my try:

public func toNSDate(wallTime: dispatch_time_t)->NSDate {
    let wallTimeAsSeconds = Double(wallTime) / Double(NSEC_PER_SEC)
    let date = NSDate(timeIntervalSince1970: wallTimeAsSeconds)
    return date
}

The resulting NSDate is not just off, but somewhat hilariously off, like five hundred years or something. As Martin R pointed out, the problem is that dispatch_time_t is an opaque value, with an undocumented representation of time.

Does anyone know how to do this?

EDIT: if the process of creating the walltime is confusing, this is basically what's going on:

NSDate defines time with a Double, and everything after the decimal point is the nanoseconds. dispatch_time, which can create a walltime, defines time with UInt64, so you have to convert between Double and UInt64 to use it. To do that conversion you need to use a timespec, which takes seconds and nanoseconds as separate arguments, each of which must be Int.

A whole lotta convertin' going on!



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire