mutualmobile/MMRecord

Support for timestamps?

Closed this issue · 5 comments

Is there currently a way to handle unix timestamps rather than formatted date strings?

Example:

{
"title":"Band Of Brothers",
"first_aired":1000018800,
}

Hey Matt,

That's a really good point. I wish I had thought of that earlier. There's not a built in way to handle that, but there are three easy ways for you to implement it in your subclass.

  1. Subclass MMRecordRepresentation and MMRecordMarshaler. This will let you specify different behavior for the setValue:onRecord:attribute:dateFormatter: method on MMRecordMarshaler. Instead of using the date formatter and calling dateFromString, you can take the string value that is passed into that method as the "value" parameter, and call the appropriate methods to convert the unix time stamp into a date.

For an example, check out the MMRecordDynamicModel sub spec in the source code.

Here's a mostly complete version of what I am talking about, with some pseudocode.

@implementation MMRecordUnixDateRepresentation

- (Class)marshalerClass {
  return [MMRecordUnixDateMarshaler class];
}

@end

@implementation MMRecordUnixDateMarshaler

+ (void)setValue:(id)value
        onRecord:(MMRecord *)record
       attribute:(NSAttributeDescription *)attribute
   dateFormatter:(NSDateFormatter *)dateFormatter {
if ([attribute attributeType] != NSDateAttributeType) {
      [super setValue:value
           onRecord:record
          attribute:attribute
      dateFormatter:dateFormatter];
} else {
  // Convert date string to date

  if (theDate != nil) {
    [record setValue:theDate forKey:attribute.name];
  }
}

@end

@implementation MovieRecord

- (Class)representationClass {
  return [MMRecordUnixDateRepresentation class];
}

@end
  1. You could also use a NSValueTransformer, and make your property transformable. That would be slightly less code for you to write, but I think the above solution is better.

  2. Depending on how you use the date, you could leave the value in Core Data stored as a string, and simply write an accessor for it on your model that turns it into a NSDate. That's a pattern I follow sometimes with URL's that come back in a response. Again, while this would work, I think solution #1 is the right approach.

Let me know if you have any questions.

Thanks,

  • Conrad

Option 1 was actually how I had handled it. Thanks!

Awesome. I'm glad you got it handled.

As a follow up, do you have any thoughts about the value of providing a default behavior for this? I'm hesitant to add another configurable variable for it, but what about specifying time stamp parsing as the default behavior for dates when the dateFormatter is not provided? Any thoughts around that? My only worry about that would be if people really do need to use a date formatter, and forget, that this behavior might not be what they expect.

Cheers,

  • Conrad

I don't see the harm in doing something like the following.

+ (NSDate *)dateValueForAttribute:(NSAttributeDescription *)attribute
                        value:(id)value
                dateFormatter:(NSDateFormatter *)dateFormatter {

    if ([value isKindOfClass:[NSNumber class]]) {
        return [NSDate dateWithTimeIntervalSince1970:[value integerValue]];
    }

    if (dateFormatter != nil) {
        return [dateFormatter dateFromString:value];
    }

    return nil;
}

No new properties or setup. Defaulting to timestamp for NSDate attributes when value is of class NSNumber. Shouldn't provide unexpected results for people that forget to supply an NSDateFormatter.

I agree. I'll go ahead and add it to my to-do list. In the mean time, feel free to submit a pull request :)

Thanks,

  • Conrad