Question

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.

Was it helpful?

Solution

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:

https://github.com/RestKit/RestKit/issues/1587

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top