2012-07-31

JSON, .NET and NSDate Redux

Here’s a version of my JSON date to NSDate conversion function updated to convert correctly to the local timezone.


/**
 * Converts a .NET JSON date in the format "/Date(x)/" to an NSDate object.
 * @param string The NSString to convert.
 * @return the NSDate object.
 */
(NSDate*)jsonStringToNSDate(NSString* string) {

    if (string == nil) return nil;

    // If we encounter .NET's minimum date value we treat it as nil.
    if ([string isEqualToString:@"/Date(-59011459200000)/"]) return nil;

    // Extract the numeric part of the date.  Dates should be in the format
    // "/Date(x)/", where x is a number.  This format is supplied automatically
    // by JSON serialisers in .NET.
    NSRange range = NSMakeRange(6, [string length] - 8);
    NSString* substring = [string substringWithRange:range];

    NSNumberFormatter* formatter = [[NSNumberFormatter alloc] init];
    NSNumber* milliseconds = [formatter numberFromString:substring];

    [formatter release];

    // NSTimeInterval is specified in seconds.  The value we get back from the
    // web service is specified in milliseconds.  Both values are since 1st Jan
    // 1970 (epoch).
    NSTimeInterval seconds = [milliseconds longLongValue] / 1000.0;

    seconds += [[NSTimeZone localTimeZone] secondsFromGMT];

    return [NSDate dateWithTimeIntervalSince1970:seconds];
}

Edit: Fixed to return milliseconds as the fractional part of the “seconds” value.

2012-01-24

JSON, .NET and NSDate

If you’re trying to access a JSON web service created using .NET from an iOS device, you’ve probably discovered that dates are produced in a less than useful format:

/Date(1233423345345)/

The rationale for the date format can be found here, but it’s basically a call to the JavaScript Date object constructor. The numeric value represents the number of milliseconds since 1970-01-01.

Below I’ve added a handy Objective-C function that will extract the value and return an NSDate object. Note that we’re losing accuracy by magnitudes as we translate from .NET DateTime objects (which measure time in ticks) to JavaScript Date objects (which measure time in milliseconds) and finally to iOS NSDate objects (which measure time in seconds).


/**
 * Converts a .NET JSON date in the format "/Date(x)/" to an NSDate object.
 * @param string The NSString to convert.
 * @return the NSDate object.
 */
(NSDate*)jsonStringToNSDate(NSString* string) {

    // Extract the numeric part of the date.  Dates should be in the format
    // "/Date(x)/", where x is a number.  This format is supplied automatically
    // by JSON serialisers in .NET.
    NSRange range = NSMakeRange(6, [string length] - 8);
    NSString* substring = [string substringWithRange:range];

    // Have to use a number formatter to extract the value from the string into
    // a long long as the longLongValue method of the string doesn't seem to
    // return anything useful - it is always grossly incorrect.
    NSNumberFormatter* formatter = [[NSNumberFormatter alloc] init];
    NSNumber* milliseconds = [formatter numberFromString:substring];

    [formatter release];

    // NSTimeInterval is specified in seconds.  The value we get back from the
    // web service is specified in milliseconds.  Both values are since 1st Jan
    // 1970 (epoch).
    NSTimeInterval seconds = [milliseconds longLongValue] / 1000;

    return [NSDate dateWithTimeIntervalSince1970:seconds];
}

2008-11-01

More Bitmaps and Calendar Fixes

The bitmap class introduced in the last post is now part of the SuperBitmap. The SuperBitmap class has retained the same API, but it now is just a facade wrapped around an instance of the Bitmap class. The Bitmap does all of the hard work.

I’ve made a couple of amendments to the Calendar and Date classes, too. The Date class now has its equals and not-equals operators overloaded, whilst the Calendar now shows Monday as the first column (instead of Sunday). It also handles clicks on buttons correctly if that button represents the currently-selected day in a different month/year.

2008-10-28

Dates and Text Wrapping

Couple of changes today. The Date class introduced yesterday now has a more optimal “calculateWeekDay()” method, thanks to Jeff. It still seems to work correctly with the calendar, which is curious, because I’m sure it was previously returning “0” as the value for Sunday whereas it now returns “7”. I must be doing some modulus stuff in the Calendar class.

Secondly, the “wrap()” function in the Text class should now be rather faster than before. Instead of re-wrapping the entire string every time something is inserted, appended or removed from the string, it now locates the line of text that contains the modification and re-wraps from that point forward.

I’d tried to implement this a few days ago but came across a couple of problems. First of all, locating the line of text in which the modification fell was slightly tricky. I’d decided to use a binary search (obvious enough), but came unstuck because I was looking for a value that fell within the range indicated by two values in the wrapping data array. I wasn’t searching for an exact match, but a match between two values. Turned out to be fairly easy to implement once I’d scratched it down on paper.

Secondly, the wrap() function remembers the width (in pixels) of the widest line of text to help with other routines elsewhere in the class. If we try to wrap the text from line n, ignoring the previous lines, and the widest line is actually n-1, we won’t have the correct width. We’ll just have the width of the widest line in the range from n to the last line of text (if we ignore the old value we stored) or the width of a line that may no longer exist (if we use the old value).

The solution to that was pretty straightforward, too. I added a second vector to store the widths of every new widest line that the wrap routine comes across, along with the index of that line in the wrapping data vector. So, if the first line is 10px wide, that’s the widest line we’ve seen up until that point, so we add width 10 and index 0 to the vector. If the second line is 8px wide, we ignore it as it is thinner than the currently-identified widest line. If the third line is 20px wide, we add width 20 and index 2 to the vector. That way, when we re-wrap from line n, we discard all of the longest line data from the vector from line n onwards. The last entry in the width vector is then the width of the longest line in the text we’re not re-wrapping.

The upshot of all this is that if a char is appended to a string 100 lines long, only the last line is re-wrapped. Previously, all 100 lines would be re-wrapped.

2008-10-26

Calendars and Dates

Here’s a new gadget that might prove useful to those people determined to create a replacement for DSOrganise:

Yep, it’s a calendar/date picker. It raises EVENT_ACTION events each time a new day is clicked. The left and right arrows page through the months and years.

Working out the layout of a calendar is actually very simple. It’s much simpler than I was expecting it to be. First of all, we make a few assumptions:

  • We will only show one month at a time (though we will show days that border the start and end of the current month)
  • We will always have 7 columns (7 days in the week)
  • We will always have 6 rows (this caters for the worst-case scenario, or largest number of visible days, and sticking to this reduces the complexity of the algorithms we need to use)

Once we’ve got that set up, we need to know what day of the week the current month starts on. The magic for this is handled inside a new Date class that can manipulate the days, months and years of a given date, the logic for which came from here (note that the rest of that site seems to be totally bonkers). If we know what day of the week the month starts on, we can generate all of the preceding day buttons, then the buttons for the current month, and finally any buttons from the next month.

Using the Calendar gadget is simple. It automatically grows and shrinks to fit within the dimensions specified in its constructor, it raises an EVENT_ACTION event when a day is clicked (as noted previously), and it has methods to set and get the date. It doesn’t inherit from the Window class, so it can be added to screens or an existing window alongside other gadges. There’s an example in the “examples” folder.

Two caveats with the Calendar and Date classes at the moment. I’m not sure that Date::addDays() works correctly for negative days (need to write a test, but as it’s not used by the Calendar it’s not a problem right now) and the Calendar doesn’t have a resize() function.