简体   繁体   中英

Convert .NET DateTime.Ticks Property to Date in Objective-C

I have a timestamp that represents the the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001 (according to http://msdn.microsoft.com/en-us/library/system.datetime.ticks.aspx ). This value is generated by a server written in C#, but I need to convert this to a date in Objective-C on iOS.

For example, the timestamp 634794644225861250 is supposed to give a date of August 2, 2012.

This C# code might help you:

// The Unix epoch is 1970-01-01 00:00:00.000
DateTime   UNIX_EPOCH = new DateTime( 1970 , 1 , 1 ) ;

// The Unix epoch represented in CLR ticks.
// This is also available as UNIX_EPOCH.Ticks
const long UNIX_EPOCH_IN_CLR_TICKS = 621355968000000000 ;

// A CLR tick is 1/10000000 second (100ns).
// Available as Timespan.TicksPerSecond
const long CLR_TICKS_PER_SECOND = 10000000 ;

DateTime now       = DateTime.Now                        ; // current moment in time
long     ticks_now = now.Ticks                           ; // get its number of tics
long     ticks     = ticks_now - UNIX_EPOCH_IN_CLR_TICKS ; // compute the current moment in time as the number of ticks since the Unix epoch began.
long     time_t    = ticks / CLR_TICKS_PER_SECOND        ; // convert that to a time_t, the number of seconds since the Unix Epoch
DateTime computed  = EPOCH.AddSeconds( time_t )          ; // and convert back to a date time value

// 'computed' is the the current time with 1-second precision.

Once you have your time_t value, the number of seconds since the Unix epoch began, you should be able to get an NSDATE in Objective-C thusly:

NSDate* myNSDate = [NSDate dateWithTimeIntervalSince1970:<my_time_t_value_here> ] ;

which see: https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/Reference/Reference.html

On iOS you cannot use dateWithString but you can still do it easily. This solution should work on both iOS and Mac. (note: I'm typing it here, not tested)

@interface NSDate (CLRTicks)

+(NSDate*)dateWithCLRTicks:(long)ticks;

@end



@implementation NSDate (CLRTicks)

+(NSDate*)dateWithCLRTicks:(long)ticks
{
    return [NSDate dateWithTimeIntervalSince1970: (ticks-621355968000000000L)/10000000.0]
}

@end

It is basically the same solution Nicholas posted, except in a better form. You should probably make it even better by defining the constants symbolically.

Add a category for NSDate:

@implementation NSDate (CLRTicks)

+ (NSDate *)dateWithCLRTicks:(int64_t)ticks {
    return [NSDate dateWithCLRTicks:ticks withTimeIntervalAddition:0.0];
}

+ (NSDate *)dateWithCLRTicks:(int64_t)ticks withTimeIntervalAddition:(NSTimeInterval)timeIntervalAddition {
    const double GMTOffset = [[NSTimeZone defaultTimeZone] secondsFromGMT];
    const int64_t CLROffset = 621355968000000000;
    double timeStamp = ((double)(ticks - CLROffset) / 10000000.0) - GMTOffset + timeIntervalAddition;

    return [NSDate dateWithTimeIntervalSince1970:timeStamp];
}

@end

Did not do all the computations, but your leap year computation is incomplete.

You get a leap year every 4 years. But you skip one every 100 years. And you do not skip it every 400, which is why 2000 was a leap year but 1900 was not.

For example:

2012 is a leap year (divisible by 4 but not 100) 2100 is not a leap year (divisible by 100 but not 400) 2400 is a leap year (divisible 400)

In cocoa you can use NSDate.

NSDate* reference = [NSDate dateWithString:@"0001-01-01 00:00:00 +0000"];
NSDate* myDate = [NSDate dateWithTimeInterval: (ticks/10000000.0)
                                    sinceDate: reference];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM