avoid day long gaps in sample data (#20897) (#21070)

* avoid day long gaps in sample data

* avoid using toISOString to avoid an timezone problems

* unskip sample test now that problem is fixed

* use much better cj algorithm for translating time

* cjcenizal review updates

* update funtion name in install.js

* push source reference date back a week
This commit is contained in:
Nathan Reese 2018-07-23 06:20:01 -06:00 committed by GitHub
parent 0a253604f5
commit 286843ac64
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 193 additions and 128 deletions

View file

@ -113,7 +113,7 @@ export function flightsSpecProvider() {
}
},
timeFields: ['timestamp'],
currentTimeMarker: '2018-01-02T00:00:00',
currentTimeMarker: '2018-01-09T00:00:00',
preserveDayOfWeekTimeOfDay: true,
savedObjects: savedObjects,
};

View file

@ -21,7 +21,11 @@ import Joi from 'joi';
import { loadData } from './lib/load_data';
import { createIndexName } from './lib/create_index_name';
import { adjustTimestamp } from './lib/adjust_timestamp';
import {
dateToIso8601IgnoringTime,
translateTimeRelativeToDifference,
translateTimeRelativeToWeek
} from './lib/translate_timestamp';
export const createInstallRoute = () => ({
path: '/api/sample_data/{id}',
@ -81,12 +85,13 @@ export const createInstallRoute = () => ({
return reply(errMsg).code(err.status);
}
const now = new Date();
const currentTimeMarker = new Date(Date.parse(sampleDataset.currentTimeMarker));
const nowReference = dateToIso8601IgnoringTime(new Date());
function updateTimestamps(doc) {
sampleDataset.timeFields.forEach(timeFieldName => {
if (doc[timeFieldName]) {
doc[timeFieldName] = adjustTimestamp(doc[timeFieldName], currentTimeMarker, now, sampleDataset.preserveDayOfWeekTimeOfDay);
doc[timeFieldName] = sampleDataset.preserveDayOfWeekTimeOfDay
? translateTimeRelativeToWeek(doc[timeFieldName], sampleDataset.currentTimeMarker, nowReference)
: translateTimeRelativeToDifference(doc[timeFieldName], sampleDataset.currentTimeMarker, nowReference);
}
});
return doc;

View file

@ -1,48 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
const MILLISECONDS_IN_DAY = 86400000;
/**
* Convert timestamp to timestamp that is relative to now
*
* @param {String} timestamp ISO8601 formated data string YYYY-MM-dd'T'HH:mm:ss.SSS
* @param {Date} currentTimeMarker "now" reference marker in sample dataset
* @param {Date} now
* @param {Boolean} preserveDayOfWeekTimeOfDay
* @return {String} ISO8601 formated data string YYYY-MM-dd'T'HH:mm:ss.SSS of timestamp adjusted to now
*/
export function adjustTimestamp(timestamp, currentTimeMarker, now, preserveDayOfWeekTimeOfDay) {
const timestampDate = new Date(Date.parse(timestamp));
if (!preserveDayOfWeekTimeOfDay) {
// Move timestamp relative to now, preserving distance between currentTimeMarker and timestamp
const timeDelta = timestampDate.getTime() - currentTimeMarker.getTime();
return (new Date(now.getTime() + timeDelta)).toISOString();
}
// Move timestamp to current week, preserving day of week and time of day
const weekDelta = Math.round((timestampDate.getTime() - currentTimeMarker.getTime()) / (MILLISECONDS_IN_DAY * 7));
const dayOfWeekDelta = timestampDate.getDay() - now.getDay();
const daysDelta = dayOfWeekDelta * MILLISECONDS_IN_DAY + (weekDelta * MILLISECONDS_IN_DAY * 7);
const yearMonthDay = (new Date(now.getTime() + daysDelta)).toISOString().substring(0, 10);
return `${yearMonthDay}T${timestamp.substring(11)}`;
}

View file

@ -1,73 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { adjustTimestamp } from './adjust_timestamp';
const currentTimeMarker = new Date(Date.parse('2018-01-02T00:00:00Z'));
const now = new Date(Date.parse('2018-04-25T18:24:58.650Z')); // Wednesday
describe('relative to now', () => {
test('adjusts time to 10 minutes in past from now', () => {
const originalTimestamp = '2018-01-01T23:50:00Z'; // -10 minutes relative to currentTimeMarker
const timestamp = adjustTimestamp(originalTimestamp, currentTimeMarker, now, false);
expect(timestamp).toBe('2018-04-25T18:14:58.650Z');
});
test('adjusts time to 1 hour in future from now', () => {
const originalTimestamp = '2018-01-02T01:00:00Z'; // + 1 hour relative to currentTimeMarker
const timestamp = adjustTimestamp(originalTimestamp, currentTimeMarker, now, false);
expect(timestamp).toBe('2018-04-25T19:24:58.650Z');
});
});
describe('preserve day of week and time of day', () => {
test('adjusts time to monday of the same week as now', () => {
const originalTimestamp = '2018-01-01T23:50:00Z'; // Monday, same week relative to currentTimeMarker
const timestamp = adjustTimestamp(originalTimestamp, currentTimeMarker, now, true);
expect(timestamp).toBe('2018-04-23T23:50:00Z');
});
test('adjusts time to friday of the same week as now', () => {
const originalTimestamp = '2017-12-29T23:50:00Z'; // Friday, same week relative to currentTimeMarker
const timestamp = adjustTimestamp(originalTimestamp, currentTimeMarker, now, true);
expect(timestamp).toBe('2018-04-27T23:50:00Z');
});
test('adjusts time to monday of the previous week as now', () => {
const originalTimestamp = '2017-12-25T23:50:00Z'; // Monday, previous week relative to currentTimeMarker
const timestamp = adjustTimestamp(originalTimestamp, currentTimeMarker, now, true);
expect(timestamp).toBe('2018-04-16T23:50:00Z');
});
test('adjusts time to friday of the week after now', () => {
const originalTimestamp = '2018-01-05T23:50:00Z'; // Friday, next week relative to currentTimeMarker
const timestamp = adjustTimestamp(originalTimestamp, currentTimeMarker, now, true);
expect(timestamp).toBe('2018-05-04T23:50:00Z');
});
test('adjusts timestamp to correct day of week even when UTC day is on different day.', () => {
const currentTimeMarker = new Date(Date.parse('2018-01-02T00:00:00')); // Tuesday
const now = new Date(Date.parse('2018-06-14T10:38')); // Thurs
const originalTimestamp = '2018-01-01T17:57:25'; // Monday
const timestamp = adjustTimestamp(originalTimestamp, currentTimeMarker, now, true);
expect(timestamp).toBe('2018-06-11T17:57:25'); // Monday
});
});

View file

@ -0,0 +1,75 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
const MILLISECONDS_IN_DAY = 86400000;
function iso8601ToDateIgnoringTime(iso8601) {
const split = iso8601.split('-');
if (split.length < 3) {
throw new Error('Unexpected timestamp format, expecting YYYY-MM-DDTHH:mm:ss');
}
const year = parseInt(split[0]);
const month = parseInt(split[1]) - 1; // javascript months are zero-based indexed
const date = parseInt(split[2]);
return new Date(year, month, date);
}
export function dateToIso8601IgnoringTime(date) {
// not using "Date.toISOString" because only using Date methods that deal with local time
const year = date.getFullYear();
const month = date.getMonth() + 1;
const monthString = month < 10 ? `0${month}` : `${month}`;
const dateString = date.getDate() < 10 ? `0${date.getDate()}` : `${date.getDate()}`;
return `${year}-${monthString}-${dateString}`;
}
// Translate source timestamp by targetReference timestamp,
// perserving the distance between source and sourceReference
export function translateTimeRelativeToDifference(source, sourceReference, targetReference) {
const sourceDate = iso8601ToDateIgnoringTime(source);
const sourceReferenceDate = iso8601ToDateIgnoringTime(sourceReference);
const targetReferenceDate = iso8601ToDateIgnoringTime(targetReference);
const timeDelta = sourceDate.getTime() - sourceReferenceDate.getTime();
const translatedDate = (new Date(targetReferenceDate.getTime() + timeDelta));
return `${dateToIso8601IgnoringTime(translatedDate)}T${source.substring(11)}`;
}
// Translate source timestamp by targetReference timestamp,
// perserving the week distance between source and sourceReference and day of week of the source timestamp
export function translateTimeRelativeToWeek(source, sourceReference, targetReference) {
const sourceReferenceDate = iso8601ToDateIgnoringTime(sourceReference);
const targetReferenceDate = iso8601ToDateIgnoringTime(targetReference);
// If these dates were in the same week, how many days apart would they be?
const dayOfWeekDelta = sourceReferenceDate.getDay() - targetReferenceDate.getDay();
// If we pretend that the targetReference is actually the same day of the week as the
// sourceReference, then we can translate the source to the target while preserving their
// days of the week.
const normalizationDelta = dayOfWeekDelta * MILLISECONDS_IN_DAY;
const normalizedTargetReference =
dateToIso8601IgnoringTime(new Date(targetReferenceDate.getTime() + normalizationDelta));
return translateTimeRelativeToDifference(
source,
sourceReference,
normalizedTargetReference);
}

View file

@ -0,0 +1,107 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { translateTimeRelativeToWeek } from './translate_timestamp';
describe('translateTimeRelativeToWeek', () => {
const sourceReference = '2018-01-02T00:00:00'; //Tuesday
const targetReference = '2018-04-25T18:24:58.650'; // Wednesday
describe('2 weeks before', () => {
test('should properly adjust timestamp when day is before targetReference day of week', () => {
const source = '2017-12-18T23:50:00'; // Monday, -2 week relative to sourceReference
const timestamp = translateTimeRelativeToWeek(source, sourceReference, targetReference);
expect(timestamp).toBe('2018-04-09T23:50:00'); // Monday 2 week before targetReference week
});
test('should properly adjust timestamp when day is same as targetReference day of week', () => {
const source = '2017-12-20T23:50:00'; // Wednesday, -2 week relative to sourceReference
const timestamp = translateTimeRelativeToWeek(source, sourceReference, targetReference);
expect(timestamp).toBe('2018-04-11T23:50:00'); // Wednesday 2 week before targetReference week
});
test('should properly adjust timestamp when day is after targetReference day of week', () => {
const source = '2017-12-22T16:16:50'; // Friday, -2 week relative to sourceReference
const timestamp = translateTimeRelativeToWeek(source, sourceReference, targetReference);
expect(timestamp).toBe('2018-04-13T16:16:50'); // Friday 2 week before targetReference week
});
});
describe('week before', () => {
test('should properly adjust timestamp when day is before targetReference day of week', () => {
const source = '2017-12-25T23:50:00'; // Monday, -1 week relative to sourceReference
const timestamp = translateTimeRelativeToWeek(source, sourceReference, targetReference);
expect(timestamp).toBe('2018-04-16T23:50:00'); // Monday 1 week before targetReference week
});
test('should properly adjust timestamp when day is same as targetReference day of week', () => {
const source = '2017-12-27T23:50:00'; // Wednesday, -1 week relative to sourceReference
const timestamp = translateTimeRelativeToWeek(source, sourceReference, targetReference);
expect(timestamp).toBe('2018-04-18T23:50:00'); // Wednesday 1 week before targetReference week
});
test('should properly adjust timestamp when day is after targetReference day of week', () => {
const source = '2017-12-29T16:16:50'; // Friday, -1 week relative to sourceReference
const timestamp = translateTimeRelativeToWeek(source, sourceReference, targetReference);
expect(timestamp).toBe('2018-04-20T16:16:50'); // Friday 1 week before targetReference week
});
});
describe('same week', () => {
test('should properly adjust timestamp when day is before targetReference day of week', () => {
const source = '2018-01-01T23:50:00'; // Monday, same week relative to sourceReference
const timestamp = translateTimeRelativeToWeek(source, sourceReference, targetReference);
expect(timestamp).toBe('2018-04-23T23:50:00'); // Monday same week as targetReference
});
test('should properly adjust timestamp when day is same as targetReference day of week', () => {
const source = '2018-01-03T23:50:00'; // Wednesday, same week relative to sourceReference
const timestamp = translateTimeRelativeToWeek(source, sourceReference, targetReference);
expect(timestamp).toBe('2018-04-25T23:50:00'); // Wednesday same week as targetReference
});
test('should properly adjust timestamp when day is after targetReference day of week', () => {
const source = '2018-01-05T16:16:50'; // Friday, same week relative to sourceReference
const timestamp = translateTimeRelativeToWeek(source, sourceReference, targetReference);
expect(timestamp).toBe('2018-04-27T16:16:50'); // Friday same week as targetReference
});
});
describe('week after', () => {
test('should properly adjust timestamp when day is before targetReference day of week', () => {
const source = '2018-01-08T23:50:00'; // Monday, 1 week after relative to sourceReference
const timestamp = translateTimeRelativeToWeek(source, sourceReference, targetReference);
expect(timestamp).toBe('2018-04-30T23:50:00'); // Monday 1 week after targetReference week
});
test('should properly adjust timestamp when day is same as targetReference day of week', () => {
const source = '2018-01-10T23:50:00'; // Wednesday, same week relative to sourceReference
const timestamp = translateTimeRelativeToWeek(source, sourceReference, targetReference);
expect(timestamp).toBe('2018-05-02T23:50:00'); // Wednesday 1 week after targetReference week
});
test('should properly adjust timestamp when day is after targetReference day of week', () => {
const source = '2018-01-12T16:16:50'; // Friday, same week relative to sourceReference
const timestamp = translateTimeRelativeToWeek(source, sourceReference, targetReference);
expect(timestamp).toBe('2018-05-04T16:16:50'); // Friday 1 week after targetReference week
});
});
});

View file

@ -50,8 +50,7 @@ export default function ({ getService, getPageObjects }) {
expect(isInstalled).to.be(true);
});
// Skipping issue # 20807
describe.skip('dashboard', () => {
describe('dashboard', () => {
after(async () => {
await PageObjects.common.navigateToUrl('home', 'tutorial_directory/sampleData');
await PageObjects.header.waitUntilLoadingHasFinished();