summaryrefslogtreecommitdiff
path: root/jstests/aggregation/expressions/object_ids_for_date_expressions.js
blob: dae3ce0d280e9c7a4a17315f533ca753f02d9269 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// SERVER-9406: Allow ObjectId type to be treated as a date in date related expressions

(function() {
    "use strict";

    load('jstests/libs/dateutil.js');

    const coll = db.server9406;
    let testOpCount = 0;

    coll.drop();

    // Seed collection so that the pipeline will execute.
    assert.writeOK(coll.insert({}));

    function makeObjectIdFromDate(dt) {
        try {
            return new ObjectId((dt.getTime() / 1000).toString(16) + "f000000000000000");
        } catch (e) {
            assert("Invalid date for conversion to Object Id: " + dt);
        }
    }

    /**
     *  Helper for testing that 'op' on 'value' is the same for dates as equivalent ObjectIds
     *  'value' is either a date value, or an object containing field 'date'.
     */
    function testOp(op, value) {
        testOpCount++;

        let pipeline = [{$project: {_id: 0, result: {}}}];
        pipeline[0].$project.result[op] = value;
        let res1 = coll.aggregate(pipeline).toArray()[0];
        if (value.date) {
            value.date = makeObjectIdFromDate(value.date);
        } else {
            value = makeObjectIdFromDate(value);
        }
        pipeline[0].$project.result[op] = value;
        let res2 = coll.aggregate(pipeline).toArray()[0];

        assert.eq(res2.result, res1.result, tojson(pipeline));
    }

    testOp('$dateToString', {date: new Date("1980-12-31T23:59:59Z"), format: "%V-%G"});
    testOp('$dateToString', {date: new Date("1980-12-31T23:59:59Z"), format: "%G-%V"});

    const years = [
        2002,  // Starting and ending on Tuesday.
        2014,  // Starting and ending on Wednesday.
        2015,  // Starting and ending on Thursday.
        2010,  // Starting and ending on Friday.
        2011,  // Starting and ending on Saturday.
        2006,  // Starting and ending on Sunday.
        1996,  // Starting on Monday, ending on Tuesday.
        2008,  // Starting on Tuesday, ending on Wednesday.
        1992,  // Starting on Wednesday, ending on Thursday.
        2004,  // Starting on Thursday, ending on Friday.
        2016,  // Starting on Friday, ending on Saturday.
        2000,  // Starting on Saturday, ending on Sunday (special).
        2012   // Starting on Sunday, ending on Monday.
    ];

    const day = 1;
    years.forEach(function(year) {
        // forEach starts indexing at zero but weekdays start with Monday on 1 so we add +1.
        let newYear = DateUtil.getNewYear(year);
        let endOfFirstWeekInYear = DateUtil.getEndOfFirstWeekInYear(year, day);
        let startOfSecondWeekInYear = DateUtil.getStartOfSecondWeekInYear(year, day);
        let birthday = DateUtil.getBirthday(year);
        let newYearsEve = DateUtil.getNewYearsEve(year);
        let now = new Date();
        now.setYear(year);
        now.setMilliseconds(0);

        testOp('$isoDayOfWeek', newYear);
        testOp('$isoDayOfWeek', endOfFirstWeekInYear);
        testOp('$isoDayOfWeek', startOfSecondWeekInYear);
        testOp('$isoWeekYear', birthday);

        testOp('$isoWeek', newYear);
        testOp('$isoWeek', now);
        testOp('$isoWeekYear', newYear);
        testOp('$isoWeek', endOfFirstWeekInYear);
        testOp('$dateToString', {format: '%G-W%V-%u', date: newYear});
        testOp('$isoWeek', endOfFirstWeekInYear);
        testOp('$year', endOfFirstWeekInYear);
        testOp('$month', endOfFirstWeekInYear);
        testOp('$dayOfMonth', endOfFirstWeekInYear);
        testOp('$dayOfWeek', birthday);
        testOp('$dayOfWeek', newYearsEve);
        testOp('$minute', newYearsEve);
        testOp('$second', now);
        testOp('$millisecond', newYear);

    });
    assert.eq(testOpCount, 236, 'Expected 236 tests to run');
})();