mongo/jstests/aggregation/expressions/date_trunc.js

332 lines
12 KiB
JavaScript

/**
* Tests $dateTrunc expression.
* @tags: [
* ]
*/
import "jstests/libs/query/sbe_assert_error_override.js";
import {executeAggregationTestCase} from "jstests/libs/query/aggregation_pipeline_utils.js";
const testDB = db.getSiblingDB(jsTestName());
const coll = testDB.collection;
// Drop the test database.
assert.commandWorked(testDB.dropDatabase());
const someDate = new Date("2020-11-01T18:23:36Z");
const aggregationPipelineWithDateTrunc = [
{
$project: {
_id: false,
date_trunc: {$dateTrunc: {date: "$date", unit: "$unit", binSize: "$binSize", timezone: "$timeZone"}},
},
},
];
const aggregationPipelineWithDateTruncAndStartOfWeek = [
{
$project: {
_id: false,
date_trunc: {
$dateTrunc: {
date: "$date",
unit: "$unit",
binSize: "$binSize",
timezone: "$timeZone",
startOfWeek: "$startOfWeek",
},
},
},
},
];
const testCases = [
{
// Parameters are constants, timezone is not specified.
pipeline: [
{
$project: {
_id: true,
date_trunc: {$dateTrunc: {date: new Date("2020-11-01T18:23:36Z"), unit: "hour", binSize: 2}},
},
},
],
inputDocuments: [{_id: 1}],
expectedResults: [{_id: 1, date_trunc: new Date("2020-11-01T18:00:00Z")}],
},
{
// Parameters are field paths.
pipeline: aggregationPipelineWithDateTruncAndStartOfWeek,
inputDocuments: [
{
date: new Date("2021-12-01T18:23:36Z"),
unit: "hour",
binSize: 4,
timeZone: "America/New_York",
startOfWeek: "IGNORED", // Ignored when unit is not week.
},
],
expectedResults: [{date_trunc: new Date("2021-12-01T17:00:00Z")}],
},
// Expression parsing tests.
{
// Invalid $dateTrunc expression - not an object.
pipeline: [{$project: {_id: false, date_trunc: {$dateTrunc: "A"}}}],
inputDocuments: [],
expectedErrorCode: 5439007,
},
{
// Invalid $dateTrunc expression - invalid parameter.
pipeline: [{$project: {_id: false, date_trunc: {$dateTrunc: {endDate: 1}}}}],
inputDocuments: [],
expectedErrorCode: 5439008,
},
{
// Invalid $dateTrunc expression - missing 'date' parameter.
pipeline: [{$project: {_id: false, date_trunc: {$dateTrunc: {unit: "week"}}}}],
inputDocuments: [],
expectedErrorCode: 5439009,
},
{
// Invalid $dateTrunc expression - missing 'unit' parameter.
pipeline: [{$project: {_id: false, date_trunc: {$dateTrunc: {date: someDate}}}}],
inputDocuments: [],
expectedErrorCode: 5439010,
},
// Evaluation tests.
{
// Default values are used for optional parameters (startOfWeek: "Sunday", binSize: 1,
// timezone: "UTC").
pipeline: [{$project: {_id: false, date_trunc: {$dateTrunc: {date: "$date", unit: "week"}}}}],
inputDocuments: [
{
date: new Date("2021-02-15T18:23:36Z"),
},
],
expectedResults: [{date_trunc: new Date("2021-02-14T00:00:00Z")}],
},
{
// Optional parameters are accepted.
pipeline: aggregationPipelineWithDateTruncAndStartOfWeek,
inputDocuments: [
{
date: new Date("2000-01-30T18:00:00Z"),
unit: "week",
binSize: 2,
timeZone: "America/New_York",
startOfWeek: "mon",
},
],
expectedResults: [{date_trunc: new Date("2000-01-17T05:00:00Z")}],
},
{
// 'date' is object id.
pipeline: [
{
$project: {_id: false, date_trunc: {$dateTrunc: {date: "$_id", unit: "minute", binSize: 10}}},
},
],
inputDocuments: [{_id: new ObjectId("507c7f79bcf86cd7994f6c0e") /* timestamp 2012-10-15T21:26:17Z*/}],
expectedResults: [{date_trunc: new Date("2012-10-15T21:20:00Z")}],
},
{
// 'date' is a timestamp.
pipeline: [
{
$project: {_id: false, date_trunc: {$dateTrunc: {date: "$ts", unit: "second", binSize: 10}}},
},
],
inputDocuments: [{ts: new Timestamp(1350336377 /*2012-10-15T21:26:17Z*/, 0)}],
expectedResults: [{date_trunc: new Date("2012-10-15T21:26:10Z")}],
},
{
// Invalid 'date' type.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [{date: "string", unit: "hour", binSize: 1, timeZone: "UTC"}],
expectedErrorCode: 5439012,
},
{
// Missing 'date' value in the document, invalid other fields.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [{unit: "H", binSize: "string", timeZone: 1}],
expectedResults: [{date_trunc: null}],
},
{
// Null 'date'.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [{date: null, unit: "hour", binSize: 1, timeZone: "UTC"}],
expectedResults: [{date_trunc: null}],
},
{
// Null 'unit'.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [{date: someDate, unit: null, binSize: 1, timeZone: "UTC"}],
expectedResults: [{date_trunc: null}],
},
{
// Missing 'unit' value in the document, invalid other fields.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [{date: "Invalid", binSize: "Invalid", timeZone: "Invalid"}],
expectedResults: [{date_trunc: null}],
expectedErrorCode: 5439017,
},
{
// Invalid 'unit' type.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [{date: someDate, unit: 1, binSize: 1, timeZone: "UTC"}],
expectedErrorCode: 5439013,
},
{
// Invalid 'unit' value.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [{date: someDate, unit: "century", binSize: 1, timeZone: "UTC"}],
expectedErrorCode: ErrorCodes.FailedToParse,
},
{
// Null 'binSize'.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [{date: someDate, unit: "hour", binSize: null, timeZone: "UTC"}],
expectedResults: [{date_trunc: null}],
},
{
// Missing 'binSize' value in the document, invalid other fields.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [{date: "Invalid", unit: "invalid", timeZone: "Invalid"}],
expectedResults: [{date_trunc: null}],
},
{
// Invalid 'binSize' type - string.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [{date: someDate, unit: "hour", binSize: "Number", timeZone: "UTC"}],
expectedErrorCode: 5439017,
},
{
// Invalid 'binSize' value.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [{date: someDate, unit: "hour", binSize: 0, timeZone: "UTC"}],
expectedErrorCode: 5439018,
},
{
// Invalid 'binSize' value - a float-point number not convertable to an integer is
// rejected.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [{date: someDate, unit: "hour", binSize: 2.5, timeZone: "UTC"}],
expectedErrorCode: 5439017,
},
{
// 'binSize' decimal value is accepted.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [
{
date: new Date("2020-01-30T18:59:00Z"),
unit: "minute",
binSize: NumberDecimal("15"),
timeZone: "UTC",
},
],
expectedResults: [
{
date_trunc: new Date("2020-01-30T18:45:00Z"),
},
],
},
{
// 'binSize' long value is accepted.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [
{
date: new Date("2020-01-30T18:59:00Z"),
unit: "day",
binSize: NumberLong("1"),
timeZone: "UTC",
},
],
expectedResults: [
{
date_trunc: new Date("2020-01-30T00:00:00Z"),
},
],
},
{
// 'binSize' int value is accepted.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [
{
date: new Date("2020-01-30T18:59:00.003Z"),
unit: "millisecond",
binSize: NumberInt("1000"),
timeZone: "UTC",
},
],
expectedResults: [
{
date_trunc: new Date("2020-01-30T18:59:00.000Z"),
},
],
},
{
// Null 'timezone'.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [{date: someDate, unit: "hour", binSize: 1, timeZone: null}],
expectedResults: [{date_trunc: null}],
},
{
// Missing 'timezone' value in the document, invalid other fields. Result could be a null
// answer or an error code depending whether pipeline is optimized.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [{date: 1, unit: "century", binSize: "1"}],
expectedResults: [{date_trunc: null}],
expectedErrorCode: [ErrorCodes.FailedToParse, 5439017],
},
{
// Invalid 'timezone' type.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [{date: someDate, unit: "hour", binSize: 1, timeZone: 1}],
expectedErrorCode: 40517,
},
{
// Invalid 'timezone' value.
pipeline: aggregationPipelineWithDateTrunc,
inputDocuments: [{date: someDate, unit: "hour", binSize: 1, timeZone: "America/Invalid"}],
expectedErrorCode: 40485,
},
{
// Null 'startOfWeek'.
pipeline: aggregationPipelineWithDateTruncAndStartOfWeek,
inputDocuments: [{date: someDate, unit: "week", startOfWeek: null}],
expectedResults: [{date_trunc: null}],
},
{
// Missing 'startOfWeek' value in the document, invalid other fields.
pipeline: aggregationPipelineWithDateTruncAndStartOfWeek,
inputDocuments: [{date: 1, unit: "week", binSize: "", timeZone: 1}],
expectedResults: [{date_trunc: null}],
expectedErrorCode: 5439017,
},
{
// Invalid 'startOfWeek' type.
pipeline: aggregationPipelineWithDateTruncAndStartOfWeek,
inputDocuments: [{date: someDate, unit: "week", binSize: 1, timeZone: "GMT", startOfWeek: 1}],
expectedErrorCode: 5439015,
},
{
// Invalid 'startOfWeek' type, unit is not the week.
pipeline: aggregationPipelineWithDateTruncAndStartOfWeek,
inputDocuments: [
{
date: new Date("2020-01-30T18:59:00.000Z"),
binSize: 1,
unit: "year",
timeZone: "GMT",
startOfWeek: 1,
},
],
expectedResults: [{date_trunc: new Date("2020-01-01T00:00:00.000Z")}],
},
{
// Invalid 'startOfWeek' value.
pipeline: aggregationPipelineWithDateTruncAndStartOfWeek,
inputDocuments: [{date: someDate, unit: "week", binSize: 1, timeZone: "GMT", startOfWeek: "FRIDIE"}],
expectedErrorCode: 5439016,
},
];
testCases.forEach((testCase) => executeAggregationTestCase(coll, testCase));