Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weekday fixes #49

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Conversation

yas375
Copy link
Contributor

@yas375 yas375 commented Oct 9, 2014

In continuation of #37 and #48.

IMPORTANT note: the changes itself in MTDates seems to be reasonable to me, but when I brought this version of MTDates to the production app I'm working on I see lots of failing unit tests around date calculations :( I'm going to investigate further on another day when I have more time. To be honest I'm not sure I will be able to do this until next week.

If anyone has time to test this pull request and/or do code review - I'll very appreciate your support.

pod 'MTDates', :git => 'https://github.com/yas375/MTDates.git', :commit => '9a56b67'

@Alex9779 could you please take a look at the fixes I done on top of yours? Thanks in advance!

Alex9779 and others added 4 commits October 10, 2014 00:23
fix for weekday calculation when first weekday is not 1=sunday (if set explicitly by "+ (void)mt_setFirstDayOfWeek:(NSUInteger)firstDay" or implicitly by locale)
It shouldn't return values more than 7
If today is Monday, and we say that the week starts from Friday, then
`mt_startOfCurrentWeek` for today should return Friday from the past. It
should never return a day after the receiver.
* 26 27 28 29 30 31
*/

NSDate *date = [_formatter dateFromString:@"08/20/2012 09:23am"];

[NSDate mt_setFirstDayOfWeek:1];
XCTAssertEqualObjects([[date mt_startOfCurrentWeek] mt_stringFromDateWithShortWeekdayTitle], @"Sun");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually such tests doesn't seem to be right to me... If mt_startOfCurrentWeek returns a date from wrong week (i.e. from the next week), then the test still passes because it just compared just names of the days. Maybe we should remove them and to leave only updated tests...

@yas375 yas375 mentioned this pull request Oct 9, 2014
@Alex9779
Copy link

@yas375 sure I'll have a look

@Alex9779
Copy link

So I did some test, @yas375 not with your code but some more essential test with the Apple NSDate, NSCalendar and NSDateComponents.
I used the following code:

    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *components = [[NSDateComponents alloc] init];

    //[calendar setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US"]];
    [calendar setFirstWeekday:1];
    [calendar setMinimumDaysInFirstWeek:1];

    NSLog(@"Initial first weekday: %lu", (unsigned long)[calendar firstWeekday]);
    NSLog(@"Minimum days in first week: %lu", (unsigned long)[calendar minimumDaysInFirstWeek]);

    [components setCalendar:calendar];
    [components setYear:2012];
    [components setWeekOfYear:1];

    for (int firstWeekday = 1; firstWeekday <= 7; firstWeekday++) {
        [calendar setFirstWeekday:firstWeekday];

        NSLog(@"First week day: %lu", (unsigned long)[calendar firstWeekday]);
        for (int weekday = 1; weekday <= 7; weekday++) {
            [components setWeekday:weekday];
            NSLog(@"%@", [calendar dateFromComponents:components]);
        }
    }

    //[calendar setLocale:[NSLocale localeWithLocaleIdentifier:@"de_DE"]];
    [calendar setFirstWeekday:2];
    [calendar setMinimumDaysInFirstWeek:4];

    NSLog(@"Initial first weekday: %lu", (unsigned long)[calendar firstWeekday]);
    NSLog(@"Minimum days in first week: %lu", (unsigned long)[calendar minimumDaysInFirstWeek]);

    [components setCalendar:calendar];
    [components setYear:2012];
    [components setWeekOfYear:1];

    for (int firstWeekday = 1; firstWeekday <= 7; firstWeekday++) {
        [calendar setFirstWeekday:firstWeekday];

        NSLog(@"First week day: %lu", (unsigned long)[calendar firstWeekday]);
        for (int weekday = 1; weekday <= 7; weekday++) {
            [components setWeekday:weekday];
            NSLog(@"%@", [calendar dateFromComponents:components]);
        }
    }

As you can see I use two different calendar settings one is manually the setting if I initialise the calendar directly with the English US local one is for German and Germany. I did this this way so the values are actually visible. Then I create components with year 2012 and weekOfYear 1. IMHO this should produce a date of the first day in the first week of year 2012.
The results are remarkable:

2014-10-10 13:19:22.052 WeekdayTests[11160:706210] Initial first weekday: 1
2014-10-10 13:19:22.053 WeekdayTests[11160:706210] Minimum days in first week: 1
2014-10-10 13:19:22.053 WeekdayTests[11160:706210] First week day: 1
2014-10-10 13:19:22.058 WeekdayTests[11160:706210] 2012-12-29 23:00:00 +0000
2014-10-10 13:19:22.058 WeekdayTests[11160:706210] 2012-12-30 23:00:00 +0000
2014-10-10 13:19:22.058 WeekdayTests[11160:706210] 2012-12-31 23:00:00 +0000
2014-10-10 13:19:22.058 WeekdayTests[11160:706210] 2013-01-01 23:00:00 +0000
2014-10-10 13:19:22.059 WeekdayTests[11160:706210] 2013-01-02 23:00:00 +0000
2014-10-10 13:19:22.059 WeekdayTests[11160:706210] 2013-01-03 23:00:00 +0000
2014-10-10 13:19:22.059 WeekdayTests[11160:706210] 2013-01-04 23:00:00 +0000
2014-10-10 13:19:22.059 WeekdayTests[11160:706210] First week day: 2
2014-10-10 13:19:22.059 WeekdayTests[11160:706210] 2013-01-05 23:00:00 +0000
2014-10-10 13:19:22.059 WeekdayTests[11160:706210] 2012-12-30 23:00:00 +0000
2014-10-10 13:19:22.059 WeekdayTests[11160:706210] 2012-12-31 23:00:00 +0000
2014-10-10 13:19:22.060 WeekdayTests[11160:706210] 2013-01-01 23:00:00 +0000
2014-10-10 13:19:22.060 WeekdayTests[11160:706210] 2013-01-02 23:00:00 +0000
2014-10-10 13:19:22.060 WeekdayTests[11160:706210] 2013-01-03 23:00:00 +0000
2014-10-10 13:19:22.070 WeekdayTests[11160:706210] 2013-01-04 23:00:00 +0000
2014-10-10 13:19:22.071 WeekdayTests[11160:706210] First week day: 3
2014-10-10 13:19:22.071 WeekdayTests[11160:706210] 2011-12-31 23:00:00 +0000
2014-10-10 13:19:22.071 WeekdayTests[11160:706210] 2012-01-01 23:00:00 +0000
2014-10-10 13:19:22.071 WeekdayTests[11160:706210] 2011-12-26 23:00:00 +0000
2014-10-10 13:19:22.071 WeekdayTests[11160:706210] 2011-12-27 23:00:00 +0000
2014-10-10 13:19:22.072 WeekdayTests[11160:706210] 2011-12-28 23:00:00 +0000
2014-10-10 13:19:22.072 WeekdayTests[11160:706210] 2011-12-29 23:00:00 +0000
2014-10-10 13:19:22.072 WeekdayTests[11160:706210] 2011-12-30 23:00:00 +0000
2014-10-10 13:19:22.072 WeekdayTests[11160:706210] First week day: 4
2014-10-10 13:19:22.072 WeekdayTests[11160:706210] 2012-12-29 23:00:00 +0000
2014-10-10 13:19:22.073 WeekdayTests[11160:706210] 2012-12-30 23:00:00 +0000
2014-10-10 13:19:22.073 WeekdayTests[11160:706210] 2012-12-31 23:00:00 +0000
2014-10-10 13:19:22.073 WeekdayTests[11160:706210] 2012-12-25 23:00:00 +0000
2014-10-10 13:19:22.073 WeekdayTests[11160:706210] 2012-12-26 23:00:00 +0000
2014-10-10 13:19:22.074 WeekdayTests[11160:706210] 2012-12-27 23:00:00 +0000
2014-10-10 13:19:22.074 WeekdayTests[11160:706210] 2012-12-28 23:00:00 +0000
2014-10-10 13:19:22.074 WeekdayTests[11160:706210] First week day: 5
2014-10-10 13:19:22.074 WeekdayTests[11160:706210] 2012-12-29 23:00:00 +0000
2014-10-10 13:19:22.074 WeekdayTests[11160:706210] 2012-12-30 23:00:00 +0000
2014-10-10 13:19:22.075 WeekdayTests[11160:706210] 2012-12-31 23:00:00 +0000
2014-10-10 13:19:22.075 WeekdayTests[11160:706210] 2013-01-01 23:00:00 +0000
2014-10-10 13:19:22.075 WeekdayTests[11160:706210] 2012-12-26 23:00:00 +0000
2014-10-10 13:19:22.075 WeekdayTests[11160:706210] 2012-12-27 23:00:00 +0000
2014-10-10 13:19:22.075 WeekdayTests[11160:706210] 2012-12-28 23:00:00 +0000
2014-10-10 13:19:22.076 WeekdayTests[11160:706210] First week day: 6
2014-10-10 13:19:22.076 WeekdayTests[11160:706210] 2012-12-29 23:00:00 +0000
2014-10-10 13:19:22.076 WeekdayTests[11160:706210] 2012-12-30 23:00:00 +0000
2014-10-10 13:19:22.076 WeekdayTests[11160:706210] 2012-12-31 23:00:00 +0000
2014-10-10 13:19:22.076 WeekdayTests[11160:706210] 2013-01-01 23:00:00 +0000
2014-10-10 13:19:22.076 WeekdayTests[11160:706210] 2013-01-02 23:00:00 +0000
2014-10-10 13:19:22.077 WeekdayTests[11160:706210] 2012-12-27 23:00:00 +0000
2014-10-10 13:19:22.077 WeekdayTests[11160:706210] 2012-12-28 23:00:00 +0000
2014-10-10 13:19:22.077 WeekdayTests[11160:706210] First week day: 7
2014-10-10 13:19:22.077 WeekdayTests[11160:706210] 2012-12-29 23:00:00 +0000
2014-10-10 13:19:22.078 WeekdayTests[11160:706210] 2012-12-30 23:00:00 +0000
2014-10-10 13:19:22.078 WeekdayTests[11160:706210] 2012-12-31 23:00:00 +0000
2014-10-10 13:19:22.078 WeekdayTests[11160:706210] 2013-01-01 23:00:00 +0000
2014-10-10 13:19:22.078 WeekdayTests[11160:706210] 2013-01-02 23:00:00 +0000
2014-10-10 13:19:22.078 WeekdayTests[11160:706210] 2013-01-03 23:00:00 +0000
2014-10-10 13:19:22.079 WeekdayTests[11160:706210] 2012-12-28 23:00:00 +0000
2014-10-10 13:19:22.079 WeekdayTests[11160:706210] Initial first weekday: 2
2014-10-10 13:19:22.079 WeekdayTests[11160:706210] Minimum days in first week: 4
2014-10-10 13:19:22.079 WeekdayTests[11160:706210] First week day: 1
2014-10-10 13:19:22.080 WeekdayTests[11160:706210] 2012-12-29 23:00:00 +0000
2014-10-10 13:19:22.080 WeekdayTests[11160:706210] 2012-12-30 23:00:00 +0000
2014-10-10 13:19:22.080 WeekdayTests[11160:706210] 2012-12-31 23:00:00 +0000
2014-10-10 13:19:22.080 WeekdayTests[11160:706210] 2013-01-01 23:00:00 +0000
2014-10-10 13:19:22.080 WeekdayTests[11160:706210] 2013-01-02 23:00:00 +0000
2014-10-10 13:19:22.081 WeekdayTests[11160:706210] 2013-01-03 23:00:00 +0000
2014-10-10 13:19:22.081 WeekdayTests[11160:706210] 2013-01-04 23:00:00 +0000
2014-10-10 13:19:22.081 WeekdayTests[11160:706210] First week day: 2
2014-10-10 13:19:22.081 WeekdayTests[11160:706210] 2013-01-05 23:00:00 +0000
2014-10-10 13:19:22.081 WeekdayTests[11160:706210] 2012-12-30 23:00:00 +0000
2014-10-10 13:19:22.082 WeekdayTests[11160:706210] 2012-12-31 23:00:00 +0000
2014-10-10 13:19:22.082 WeekdayTests[11160:706210] 2013-01-01 23:00:00 +0000
2014-10-10 13:19:22.082 WeekdayTests[11160:706210] 2013-01-02 23:00:00 +0000
2014-10-10 13:19:22.082 WeekdayTests[11160:706210] 2013-01-03 23:00:00 +0000
2014-10-10 13:19:22.082 WeekdayTests[11160:706210] 2013-01-04 23:00:00 +0000
2014-10-10 13:19:22.083 WeekdayTests[11160:706210] First week day: 3
2014-10-10 13:19:22.083 WeekdayTests[11160:706210] 2012-01-07 23:00:00 +0000
2014-10-10 13:19:22.083 WeekdayTests[11160:706210] 2012-01-08 23:00:00 +0000
2014-10-10 13:19:22.083 WeekdayTests[11160:706210] 2012-01-02 23:00:00 +0000
2014-10-10 13:19:22.084 WeekdayTests[11160:706210] 2012-01-03 23:00:00 +0000
2014-10-10 13:19:22.084 WeekdayTests[11160:706210] 2012-01-04 23:00:00 +0000
2014-10-10 13:19:22.084 WeekdayTests[11160:706210] 2012-01-05 23:00:00 +0000
2014-10-10 13:19:22.084 WeekdayTests[11160:706210] 2012-01-06 23:00:00 +0000
2014-10-10 13:19:22.084 WeekdayTests[11160:706210] First week day: 4
2014-10-10 13:19:22.085 WeekdayTests[11160:706210] 2012-01-07 23:00:00 +0000
2014-10-10 13:19:22.085 WeekdayTests[11160:706210] 2012-01-08 23:00:00 +0000
2014-10-10 13:19:22.085 WeekdayTests[11160:706210] 2012-01-09 23:00:00 +0000
2014-10-10 13:19:22.085 WeekdayTests[11160:706210] 2012-01-03 23:00:00 +0000
2014-10-10 13:19:22.085 WeekdayTests[11160:706210] 2012-01-04 23:00:00 +0000
2014-10-10 13:19:22.086 WeekdayTests[11160:706210] 2012-01-05 23:00:00 +0000
2014-10-10 13:19:22.086 WeekdayTests[11160:706210] 2012-01-06 23:00:00 +0000
2014-10-10 13:19:22.086 WeekdayTests[11160:706210] First week day: 5
2014-10-10 13:19:22.086 WeekdayTests[11160:706210] 2011-12-31 23:00:00 +0000
2014-10-10 13:19:22.087 WeekdayTests[11160:706210] 2012-01-01 23:00:00 +0000
2014-10-10 13:19:22.087 WeekdayTests[11160:706210] 2012-01-02 23:00:00 +0000
2014-10-10 13:19:22.087 WeekdayTests[11160:706210] 2012-01-03 23:00:00 +0000
2014-10-10 13:19:22.087 WeekdayTests[11160:706210] 2011-12-28 23:00:00 +0000
2014-10-10 13:19:22.087 WeekdayTests[11160:706210] 2011-12-29 23:00:00 +0000
2014-10-10 13:19:22.088 WeekdayTests[11160:706210] 2011-12-30 23:00:00 +0000
2014-10-10 13:19:22.088 WeekdayTests[11160:706210] First week day: 6
2014-10-10 13:19:22.088 WeekdayTests[11160:706210] 2011-12-31 23:00:00 +0000
2014-10-10 13:19:22.088 WeekdayTests[11160:706210] 2012-01-01 23:00:00 +0000
2014-10-10 13:19:22.088 WeekdayTests[11160:706210] 2012-01-02 23:00:00 +0000
2014-10-10 13:19:22.089 WeekdayTests[11160:706210] 2012-01-03 23:00:00 +0000
2014-10-10 13:19:22.089 WeekdayTests[11160:706210] 2012-01-04 23:00:00 +0000
2014-10-10 13:19:22.089 WeekdayTests[11160:706210] 2011-12-29 23:00:00 +0000
2014-10-10 13:19:22.089 WeekdayTests[11160:706210] 2011-12-30 23:00:00 +0000
2014-10-10 13:19:22.089 WeekdayTests[11160:706210] First week day: 7
2014-10-10 13:19:22.090 WeekdayTests[11160:706210] 2012-12-29 23:00:00 +0000
2014-10-10 13:19:22.090 WeekdayTests[11160:706210] 2012-12-30 23:00:00 +0000
2014-10-10 13:19:22.090 WeekdayTests[11160:706210] 2012-12-31 23:00:00 +0000
2014-10-10 13:19:22.090 WeekdayTests[11160:706210] 2013-01-01 23:00:00 +0000
2014-10-10 13:19:22.090 WeekdayTests[11160:706210] 2013-01-02 23:00:00 +0000
2014-10-10 13:19:22.091 WeekdayTests[11160:706210] 2013-01-03 23:00:00 +0000
2014-10-10 13:19:22.091 WeekdayTests[11160:706210] 2012-12-28 23:00:00 +0000
Program ended with exit code: 0

Can you explain this to me?
I cannot for myself see any sense in the results... If I use not week 1 but week 2 the results look good...
But for week 1 it is strange, really strange...

@yas375
Copy link
Contributor Author

yas375 commented Oct 17, 2014

@Alex9779 thanks a lot for the investigation! Unfortunately I still can't find some free time to deep into this. On the upcoming weekend will be busy at a hackathon so probably also won't have time, sorry :(

If anyone else wants to join the discussion - welcome ;)

@Alex9779
Copy link

Ok I did even some further test, this time I created a new OS X Cocoa Project with Xcode 6.1 in Swift and removed the main project and used only the tests.
I create a default gregorian calendar, this is set for firstWeekday = 1 ( = sunday) and minimumDaysInFirstweek = 1.
Then I create two NSDateComponents and initialize them one by setting year, month and day as the expected date, and one by setting year, weekOfYear and later weekday.
I found that in Swift getting a date from components with only year and weekOfYear set always returns a date of the 1st January, even if i set the weekOfYear > 1!
When I set the weekday too then I get different dates.
But also I do not always get what I expect.

For example with firstWeekday = 1 and minimumDaysInWeek = 1 I expect the first weekday of the first week in year 2012 (that is year = 2012, weekOfYear = 1, weekday = 1) to be the 2012-01-01 but I get 2012-12-30 while for the first weekday of the second week (that is year = 2012, weekOfYear = 2, weekday = 1) which should be 2012-01-08 I get the correct result.

With firstWeekday = 2 and minimumDaysInWeek = 4, thats the german or european standard, I expect the first weekday of the first week in year 2012 (that is year = 2012, weekOfYear = 1, weekday = 2) to be the 2012-01-01 but I get 2012-12-30 while for the first weekday of the second week (that is year = 2012, weekOfYear = 2, weekday = 2) which should be 2012-01-09 I get the correct result.

So I opened a bug report at Apple, let see what they say...

@Alex9779
Copy link

So what I wanna say with all this is that the framework of Apple may be buggy and the test of MTDates build on that system, initializing the calendar with several values, so the fix is only a fix for the values that MTDates presets for the test and my test also use that values.

This does not mean that my fix really fixes week and weekday calculations on real application!!!
We really have to think about what we test here because the tests we wrote atm are using MTDates functions which use the Apple framework to generate both, the expected dates and the test dates.

IMHO this is not really correct, we should generate the expected dates as low level as possible...

In my second test app I created them from components where I set year, month and day and used a paper calendar and really looked there with the set values of the NSCalendar in mind...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants