3

So here's the problem with doing unit tests of calendar code in Objective-C: the Timezone contains the information about daylight savings, so you write a test in the summer, expecting sunrise on June 10th to occur at 6:02 am. Your test passes, later, you are running the test when it's not DST and you get a failure, because when you get the timezone, daylightsavings is turned off.

There doesn't seem to be a simple way to just tell it to give you the timezone with dst turned on?

I was thinking about doing a category so that I would intercept the timezone call but that sounds super messy as I don't know what date you are manipulating.

Of course, I could write all my tests to check the timezone setting and then just shift all my expectations but that sounds like the worst of all possible choices.

Rob
  • 11,446
  • 7
  • 39
  • 57

2 Answers2

2

Region-specific timezones must take into account daylight saving time in order to accurately calculate intervals between two dates (and times). If you aren't interested in this, perhaps you could use a UTC “timezone” instead, which don't change at all.

For example, New Zealand Standard Time is defined as UTC+12:00, and New Zealand Daylight Saving Time is defined as UTC+13:00. Although the local time in New Zealand differs during Daylight Saving Time, the times in UTC+12:00 remain the same (that is, every other country that also uses UTC+12:00 don't magically move forward just because Daylight Saving Time has commenced in New Zealand).

You can achieve this simply by providing that UTC offset as the name:

NSTimeZone *utc_plus12 = [NSTimeZone timeZoneWithName:@"UTC+12:00"];

Find out what UTC offset your region's daylight saving time is based on and use that.

dreamlax
  • 93,976
  • 29
  • 161
  • 209
  • It's not that I'm not interested, it's that it's going to give me the DST settings for today, when the test is being run, not the date that is being tested. That's the problem? Yet, I think your solution may be a good one because I can be sure my offset from GMT will be the same no matter when the test is being run. – Rob Jan 17 '13 at 01:13
  • @Rob: Oh sorry I misread the question. I think using UTC would be a good approach, other than that you could fiddle around with `NSTimeZone` methods such as `daylightSavingTimeOffsetForDate:` (which will usually return 3600 when the time zone is in DST) and you could add this to any NSDates that need comparing against. – dreamlax Jan 17 '13 at 01:23
1

I encountered the similar problem. Finally I found OCMock and saved my life.
If you are using Cocoapods, that will be great! Here is the steps:

  1. Edit your Podfile and add a lines to import OCMock.

    target 'YourProjectTests' do
        pod 'OCMock'
    end
    
  2. Add import in your unit test class

    #import <OCMock/OCMock.h>
    
  3. Write your test case like this

    - (void)testLocalTimezoneFromPDT {
        NSTimeZone* timeZone = [NSTimeZone timeZoneWithAbbreviation:@"PDT"];
        id timeZoneMock = OCMClassMock([NSTimeZone class]);
        OCMStub([timeZoneMock localTimeZone]).andReturn(timeZone);
    
        // Implement your test case
        // XCTAssertEqual(...);
    }
    

That code will mock the original [NSTimeZone localTimeZone] method and return the static value.
In this example, we return the timezone from Pacific Daylight Time (PDT) [GMT-07:00].
When your class call [NSTimeZone localTimeZone], your class will get the timezone we set with OCMock.

Hopes this answer will help you.

Johnny
  • 1,824
  • 23
  • 16