mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-23 12:27:52 +08:00
Added RKDotNetDateFormatter to translate back and forth between NSDate and strings like /Date(1234567890123-0500)/ Also includes header docs and specs. Fixes #264
This commit is contained in:
57
Code/Support/RKDotNetDateFormatter.h
Normal file
57
Code/Support/RKDotNetDateFormatter.h
Normal file
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// RKDotNetDateFormatter.h
|
||||
// RestKit
|
||||
//
|
||||
// Created by Greg Combs on 9/8/11.
|
||||
// Copyright (c) 2011 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
A subclass of NSDateFormatter that serves as translator between ASP.NET date serializations in JSON
|
||||
strings and NSDate objects. This is useful for properly mapping these dates from an ASP.NET driven backend.
|
||||
*NOTE* - DO NOT attempt to use setDateFormat: on this class. It will return invalid results.
|
||||
*/
|
||||
@interface RKDotNetDateFormatter : NSDateFormatter {
|
||||
NSRegularExpression *dotNetExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns an NSDate object from an ASP.NET style date string respresentation, as seen in JSON.
|
||||
Acceptable examples are:
|
||||
/Date(1112715000000-0500)/
|
||||
/Date(1112715000000)/
|
||||
Where 1112715000000 is the number of milliseconds since January 1, 1970 00:00 GMT/UTC, and -0500 represents the
|
||||
timezone offset from GMT in 24-hour time.
|
||||
|
||||
*NOTE* NSDate objects do not have timezones, and you should never change an actual date value based on a
|
||||
timezone offset. However, timezones are important when presenting dates to the user. Therefore,
|
||||
If an offset is present in the ASP.NET string (it should be), we actually ignore the offset portion because
|
||||
we want to store the actual date value in its raw form, without any pollution of timezone information.
|
||||
If, on the other hand, there is no offset in the ASP.NET string, we assume GMT (+0000) anyway.
|
||||
In summation, for this class setTimeZone: is ignored except when using stringFromDate:
|
||||
|
||||
@param string The ASP.NET style string, /Date(1112715000000-0500)/
|
||||
@return An NSDate object
|
||||
@see stringFromDate
|
||||
@see NSDateFormatter
|
||||
@see NSTimeZone
|
||||
*/
|
||||
- (NSDate *)dateFromString:(NSString *)string;
|
||||
|
||||
/**
|
||||
Returns an ASP.NET style date string from an NSDate, such as /Date(1112715000000+0000)/
|
||||
Where 1112715000000 is the number of milliseconds since January 1, 1970 00:00 GMT/UTC, and +0000 is the
|
||||
timezone offset from GMT in 24-hour time.
|
||||
|
||||
*NOTE* GMT (+0000) is assumed otherwise specified via setTimeZone:
|
||||
|
||||
@param date An NSDate
|
||||
@return The ASP.NET style string, /Date(1112715000000-0500)/
|
||||
@see dateFromString
|
||||
@see NSDateFormatter
|
||||
@see NSTimeZone
|
||||
*/
|
||||
- (NSString *)stringFromDate:(NSDate *)date;
|
||||
@end
|
||||
92
Code/Support/RKDotNetDateFormatter.m
Normal file
92
Code/Support/RKDotNetDateFormatter.m
Normal file
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// RKDotNetDateFormatter.m
|
||||
// RestKit
|
||||
//
|
||||
// Created by Greg Combs on 9/8/11.
|
||||
// Copyright (c) 2011 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RKDotNetDateFormatter.h"
|
||||
#import "RestKit.h"
|
||||
|
||||
BOOL isValidRange(NSRange rangeOfMatch);
|
||||
NSTimeInterval secondsFromMilliseconds(NSTimeInterval millisecs);
|
||||
NSTimeInterval millisecondsFromSeconds(NSTimeInterval seconds);
|
||||
|
||||
@interface RKDotNetDateFormatter()
|
||||
- (NSString *)millisecondsFromString:(NSString *)string;
|
||||
@end
|
||||
|
||||
@implementation RKDotNetDateFormatter
|
||||
|
||||
- (NSDate *)dateFromString:(NSString *)string {
|
||||
NSString *milliseconds = [self millisecondsFromString:string];
|
||||
if (!milliseconds) {
|
||||
RKLogError(@"Attempted to interpret an invalid .NET date string: %@", string);
|
||||
return nil;
|
||||
}
|
||||
NSTimeInterval seconds = secondsFromMilliseconds([milliseconds doubleValue]);
|
||||
return [NSDate dateWithTimeIntervalSince1970:seconds];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)stringFromDate:(NSDate *)date {
|
||||
if (!date) {
|
||||
RKLogError(@"Attempted to represent an invalid date: %@", date);
|
||||
return nil;
|
||||
}
|
||||
NSTimeInterval milliseconds = millisecondsFromSeconds([date timeIntervalSince1970]);
|
||||
NSString *timeZoneOffset = [super stringFromDate:date];
|
||||
return [NSString stringWithFormat:@"/Date(%1.0lf%@)/", milliseconds, timeZoneOffset];
|
||||
}
|
||||
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.locale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"] autorelease];
|
||||
self.timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
|
||||
[self setDateFormat:@"ZZ"]; // GMT offset, like "-0500"
|
||||
NSString *pattern = @"\\/Date\\((\\d+)((?:[\\+\\-]\\d+)?)\\)\\/"; // /Date(mSecs)/ or /Date(mSecs-0400)/
|
||||
dotNetExpression = [[NSRegularExpression alloc] initWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:NULL];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void)dealloc {
|
||||
[dotNetExpression release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)millisecondsFromString:(NSString *)string {
|
||||
if (!string)
|
||||
return nil;
|
||||
NSTextCheckingResult *match = [dotNetExpression firstMatchInString:string options:NSMatchingCompleted range:NSMakeRange(0, [string length])];
|
||||
if (!match)
|
||||
return nil;
|
||||
NSRange millisecRange = [match rangeAtIndex:1];
|
||||
if (!isValidRange(millisecRange))
|
||||
return nil;
|
||||
//NSRange timeZoneRange = [match rangeAtIndex:2];
|
||||
NSString *milliseconds = [string substringWithRange:millisecRange];
|
||||
return milliseconds;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
BOOL isValidRange(NSRange rangeOfMatch) {
|
||||
return (!NSEqualRanges(rangeOfMatch, NSMakeRange(NSNotFound, 0)));
|
||||
}
|
||||
|
||||
|
||||
NSTimeInterval secondsFromMilliseconds(NSTimeInterval millisecs) {
|
||||
return millisecs / 1000.f;
|
||||
}
|
||||
|
||||
|
||||
NSTimeInterval millisecondsFromSeconds(NSTimeInterval seconds) {
|
||||
return seconds * 1000.f;
|
||||
}
|
||||
|
||||
@@ -12,3 +12,4 @@
|
||||
#import "RKLog.h"
|
||||
#import "NSString+RestKit.h"
|
||||
#import "RKPathMatcher.h"
|
||||
#import "RKDotNetDateFormatter.h"
|
||||
|
||||
Reference in New Issue
Block a user