I am struggling to define the global transformer for Restkit for epoch time since 1970 (JSON: "birthDay":357861600000) in milliseconds. I tried to use this code
NSDateFormatter *localOffsetDateFormatter = [[NSDateFormatter alloc] init];
[localOffsetDateFormatter setLocale:[NSLocale currentLocale]];
[localOffsetDateFormatter setDateFormat:@"SSSSSSSS.SSS"]; //and similar versions
[localOffsetDateFormatter setTimeZone:[NSTimeZone localTimeZone]];
[[RKValueTransformer defaultValueTransformer] localOffsetDateFormatter atIndex:0];
// also tried to register RKDotNetDateFormatter
It does not work the way I would expect. Or should I create a new specific NSDateFormatter similar to RKDotNetDateFormatter? Also the code above does not trigger the implementation in a custom formater in case when I use e.g. RKDotNetDateFormatter.
Thank you for a hint.
UPDATE 1: Custom formater
But is is ignored/not used by the Restkit mapping engine.
TSNEpochSince1970DateFormatter* epochSince1970Formater = [TSNEpochSince1970DateFormatter epochSince1970DateFormatterWithTimeZone:[NSTimeZone localTimeZone]];
[[RKValueTransformer defaultValueTransformer] insertValueTransformer:epochSince1970Formater atIndex:0];
TSNEpochSince1970DateFormatter.h:
@interface TSNEpochSince1970DateFormatter : NSDateFormatter
+ (instancetype)epochSince1970DateFormatterWithTimeZone:(NSTimeZone *)timeZone;
- (NSDate *)dateFromString:(NSString *)string;
- (NSString *)stringFromDate:(NSDate *)date;
@end
TSNEpochSince1970DateFormatter.m:
@implementation TSNEpochSince1970DateFormatter
+ (instancetype)epochSince1970DateFormatterWithTimeZone:(NSTimeZone *)newTimeZone
{
TSNEpochSince1970DateFormatter *formatter = [self new];
if (newTimeZone) formatter.timeZone = newTimeZone;
return formatter;
}
- (NSDate *)dateFromString:(NSString *)string
{
return [NSDate dateWithTimeIntervalSince1970:[string integerValue]];
}
- (NSString *)stringFromDate:(NSDate *)date
{
if (!date) {
TSNLogError(@"Attempted to represent an invalid date: %@", date);
return nil;
}
return [self stringForObjectValue:date];
}
- (BOOL)getObjectValue:(id *)outValue forString:(NSString *)string errorDescription:(NSString **)error
{
NSDate *date = [self dateFromString:string];
if (outValue)
*outValue = date;
return (date != nil);
}
- (NSString *)stringForObjectValue:(id)value
{
NSParameterAssert([value isKindOfClass:[NSDate class]]);
NSTimeInterval milliseconds = [(NSDate *)value timeIntervalSince1970];
return [NSString stringWithFormat:@"%1.0lf", milliseconds];
}
@end
UPDATE 2 From the RKCompoundValueTransformer implementation I can see there is already the suitable transformer called "timeIntervalSince1970ToDateValueTransformer". TSNEpochSince1970DateFormatter is mine.
(lldb) po self.valueTransformers
<__NSArrayM 0x10ef04b30>(
<TSNEpochSince1970DateFormatter: 0x109987a70>,
<RKBlockValueTransformer: 0x109d287a0, name: identityValueTransformer>,
<RKBlockValueTransformer: 0x109d296a0, name: stringToURLValueTransformer>,
<RKBlockValueTransformer: 0x109d1d640, name: decimalNumberToNumberValueTransformer>,
<RKBlockValueTransformer: 0x109d2a7c0, name: decimalNumberToStringValueTransformer>,
<RKBlockValueTransformer: 0x10ef03e90, name: numberToStringValueTransformer>,
<RKBlockValueTransformer: 0x10ef03610, name: arrayToOrderedSetValueTransformer>,
<RKBlockValueTransformer: 0x10ef02210, name: arrayToSetValueTransformer>,
<RKBlockValueTransformer: 0x10ef00a30, name: nullValueTransformer>,
<RKBlockValueTransformer: 0x10ef02700, name: keyedArchivingValueTransformer>,
<RKBlockValueTransformer: 0x10ef02830, name: stringValueTransformer>,
<RKBlockValueTransformer: 0x10ef03fd0, name: objectToCollectionValueTransformer>,
<RKBlockValueTransformer: 0x10ef02830, name: stringValueTransformer>,
<RKBlockValueTransformer: 0x10ef02b80, name: keyOfDictionaryValueTransformer>,
<RKBlockValueTransformer: 0x10ef04630, name: mutableValueTransformer>,
<RKBlockValueTransformer: 0x10ef04b00, name: iso8601TimestampToDateValueTransformer>,
<RKBlockValueTransformer: 0x10ef042d0, name: timeIntervalSince1970ToDateValueTransformer>,
<NSDateFormatter: 0x10ef04bd0>,
<NSDateFormatter: 0x10ef05fb0>
)
UPDATE 3
I have figured out the wrong date is returned by NSDate itself in [RKValueTransformers timeIntervalSince1970ToDateValueTransformer]:
[NSDate dateWithTimeIntervalSince1970:357861600000];
returns 13310-03-08 16:00:00 +0000.
The input value should be divided by 1000. The code from timeIntervalSince1970ToDateValueTransformer in RKValueTransformer can be reused in a helper class and inserted in the mapping process with
[[RKValueTransformer defaultValueTransformer] insertValueTransformer:[TSNTimeIntervalInMillisecondsSince1970ValueTransformer timeIntervalInMillisecondsSince1970ToDateValueTransformer]
atIndex:0];
UPDATE
There is already an implementation in the development branch: