开发者

CGEventTimestamp to NSDate

I'm simply trying to convert a CGEventTimestamp (which is an unsigned 64-bit integer roughly representing nanoseconds since system startup) into an NSDate. I know there's a way to convert "time since system startup" into either an NSTimeInterval or a date relative to a reference da开发者_如何学Gote, but I'm not finding it.

How do I convert a CGEventTimestamp into something NSDate will accept? Thanks.

(forgot to mention, needs to be 10.5 friendly and avoid Carbon if at all possible)


// Determine time in NSTimeInterval seconds this event took place after system start
GCEventTimestamp nanoseconds = GetIt();
NSTimeInterval seconds = (NSTimeInterval)nanoseconds / 1000000000.0;

// GetCurrentEventTime() gives you time in seconds since system start
EventTime currentTimeInSeconds = GetCurrentEventTime();

// Given this you can figure out the date of system start, and then add
// your event time
NSDate* startTime = [NSDate dateWithTimeIntervalSinceNow:-currentTimeInSeconds];
NSDate* eventTime = [startTime dateByAddingTimeInterval:seconds];


nall got me in the right direction. I slapped together a category on NSDate that takes care of the details and is both 10.5/10.6 friendly and uses no Carbon. Thanks for the help, nall!

NSDate-Additions.h

#import <Foundation/Foundation.h>
@interface NSDate (NSDate_Additions)

+(NSTimeInterval) timeIntervalSinceSystemStartup;
-(NSTimeInterval) timeIntervalSinceSystemStartup;
+(NSDate *) dateOfSystemStartup;
+(NSDate *) dateWithCGEventTimestamp:(CGEventTimestamp)cgTimestamp;

@end

NSDate-Additions.m

#import "NSDate-Additions.h"
#include <assert.h>
#include <CoreServices/CoreServices.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <unistd.h>

#if MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_5
@interface NSProcessInfo (SnowLeopard)
- (NSTimeInterval)systemUptime;
@end

@interface NSDate (SnowLeopard)
- (id)dateByAddingTimeInterval:(NSTimeInterval)seconds;
@end
#endif


// Boosted from Apple sample code
uint64_t UpTimeInNanoseconds(void)
{
    uint64_t        time;
    uint64_t        timeNano;
    static mach_timebase_info_data_t    sTimebaseInfo;

    time = mach_absolute_time();

    // Convert to nanoseconds.

    // If this is the first time we've run, get the timebase.
    // We can use denom == 0 to indicate that sTimebaseInfo is
    // uninitialised because it makes no sense to have a zero
    // denominator is a fraction.

    if ( sTimebaseInfo.denom == 0 ) {
        (void) mach_timebase_info(&sTimebaseInfo);
    }

    // Do the maths.  We hope that the multiplication doesn't
    // overflow; the price you pay for working in fixed point.

    timeNano = time * sTimebaseInfo.numer / sTimebaseInfo.denom;

    return timeNano;
}


@implementation NSDate (NSDate_Additions)

+(NSTimeInterval) timeIntervalSinceSystemStartup
{
    NSTimeInterval interval;
    long sysVersion;

    Gestalt( gestaltSystemVersion, &sysVersion );
    if( sysVersion >= 0x1060 )
        interval = [[NSProcessInfo processInfo] systemUptime];
    else
        interval = UpTimeInNanoseconds() / 1000000000.0;

    return( interval );
}

-(NSTimeInterval) timeIntervalSinceSystemStartup
{
    return( [self timeIntervalSinceDate:[NSDate dateOfSystemStartup]] );
}

+(NSDate *) dateOfSystemStartup
{
    return( [NSDate dateWithTimeIntervalSinceNow:-([NSDate timeIntervalSinceSystemStartup])] );
}

+(NSDate *) dateWithCGEventTimestamp:(CGEventTimestamp)cgTimestamp
{
    NSDate *ssuDate = nil;
    NSDate *cgDate = nil;
    long sysVersion;

    ssuDate = [NSDate dateOfSystemStartup];

    Gestalt( gestaltSystemVersion, &sysVersion );
    if( sysVersion >= 0x1060 )
        cgDate = [ssuDate dateByAddingTimeInterval:(cgTimestamp/1000000000.0)];
    else
        cgDate = [ssuDate addTimeInterval:(cgTimestamp/1000000000.0)];

    return( cgDate );
}

@end


Regarding the code NSDate-Additions.m above. The line "timeNano = time * sTimebaseInfo.numer / sTimebaseInfo.denom;" will cause memory corruption on iPhone OS 2.2.1. A fix is to use a cast like: timeNano = time * (uint64_t)sTimebaseInfo.numer / sTimebaseInfo.denom;


This is not an answer, for some reason I cannot add a comment on your post above...

I was wondering if I could use the code you pasted in an open-source project I'm contributing to (with a link to this page).

Cheers!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜