-
Notifications
You must be signed in to change notification settings - Fork 111
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
Fixing time zone problems #1624
Conversation
Signed-off-by: Lance Finfrock <lfinfrock@chef.io>
Signed-off-by: Lance Finfrock <lfinfrock@chef.io>
endDate: reportQuery.endDate.clone(), | ||
interval: reportQuery.interval, | ||
filters: Object.assign([], reportQuery.filters) | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returning a clone of the current state to avoid the state changing unintentionally
|
||
apiFilters.push({type: 'start_time', values: [value.format()]}); | ||
} | ||
|
||
if (reportQuery.endDate) { | ||
const now = moment(); | ||
const value = reportQuery.endDate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the real bug. The hour for the state was being updated here.
@@ -445,7 +446,7 @@ export class ReportingComponent implements OnInit, OnDestroy { | |||
const foundFilter = urlFilters.find( (filter: Chicklet) => filter.type === 'end_time'); | |||
|
|||
if (foundFilter !== undefined) { | |||
const endDate = moment(foundFilter.text, 'YYYY-MM-DD'); | |||
const endDate = moment(foundFilter.text + 'GMT+00:00', 'YYYY-MM-DDZ'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parsing the date as UTC. Before the date would come in as the local users timezone.
@@ -180,7 +180,8 @@ export class ReportingComponent implements OnInit, OnDestroy { | |||
const allUrlParameters$ = this.getAllUrlParameters(); | |||
|
|||
this.endDate$ = this.reportQuery.state.pipe(map((reportQuery: ReportQuery) => | |||
reportQuery.endDate.toDate())); | |||
new Date(reportQuery.endDate.year(), reportQuery.endDate.month(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Converting the moment to a date object without any time zone conversion. Where before the date's hours would be offset by the user's local timezone.
Signed-off-by: Lance Finfrock <lfinfrock@chef.io>
Signed-off-by: Lance Finfrock <lfinfrock@chef.io>
component.applyParamFilters([ | ||
{type: 'chef_tags', text: '123'}, | ||
{type: 'end_time', text: '2019-09-05'}]); | ||
expect(reportQueryService.setState).toHaveBeenCalledWith( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test would not pass anymore even though the same objects were displayed in the error. The 'getEndDate' test covers the same test case.
startDate: reportQuery.startDate.clone(), | ||
endDate: reportQuery.endDate.clone(), | ||
interval: reportQuery.interval, | ||
filters: Object.assign([], reportQuery.filters) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cleaner pattern for cloning that we (auth team) have been introducing in recent months--use the spread operator:
filters: Object.assign([], reportQuery.filters) | |
filters: [...portQuery.filters] |
@@ -68,6 +68,18 @@ describe('ReportingComponent', () => { | |||
expect(qe).not.toBeNull(); | |||
}); | |||
|
|||
it('convertMomentToDateWithoutTimezone', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency should be a verb-phrase rather than a noun, perhaps for this test:
it('convertMomentToDateWithoutTimezone', () => { | |
it('maps hour correctly without timezone', () => { |
and for the next test, looks like with timezone...?
@@ -68,6 +68,18 @@ describe('ReportingComponent', () => { | |||
expect(qe).not.toBeNull(); | |||
}); | |||
|
|||
it('convertMomentToDateWithoutTimezone', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These new tests are, I understand, specifically to cover the bug. But consider expanding them with a few other key values, typically around boundaries. There's a test helper using
in spec-helpers.ts, that makes it easy to test all equivalence classes:
using([
[23, 'an hour before end of day'],
[0, 'exactly end of day'],
[1, 'an hour after end of day']
], function (hour: number, description: string) {
it(`maps hour correctly without timezone for ${description}`, () => {
const dateBefore = moment(`20191023-${hour}00`, 'YYYYMMDD-HHMM');
const dateAfter = component.convertMomentToDateWithoutTimezone(dateBefore);
expect(dateBefore.hour()).toEqual(dateAfter.getHours());
});
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you. The using block is a nice tool.
@@ -253,7 +253,7 @@ export class ReportingComponent implements OnInit, OnDestroy { | |||
this.downloadOptsVisible = false; | |||
|
|||
const reportQuery = this.reportQuery.getReportQuery(); | |||
const filename = `${moment(reportQuery.endDate).format('YYYY-M-D')}.${format}`; | |||
const filename = `${reportQuery.endDate.format('YYYY-M-D')}.${format}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest constant width for easy filename sorting at the command line:
const filename = `${reportQuery.endDate.format('YYYY-M-D')}.${format}`; | |
const filename = `${reportQuery.endDate.format('YYYY-MM-DD')}.${format}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't feel comfortable making this change with this PR.
second: now.get('second') | ||
}).utc().endOf('day'); | ||
|
||
const value = reportQuery.endDate.clone().utc().endOf('day'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty sure you do not need the clone()
there as you are evaluating a functional sequence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is what I thought from my original PR, but the endOf('day')
function changes the original object. https://momentjs.com/docs/#/manipulating/end-of/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pulled the change down locally and ensure the correct date was selectable for my timezone as well as those across the pond
π© Description: What code changed, and why?
Fixing a bug where the compliance reporting page would not allow the user in UTC+1 view the current day. The problem was the reportQuery state was being changed unintentionally. There was also some sections of code that when converting from moment to date was switching the current hour because of time zones.
π Definition of Done
When in timezone UTC+1 the current date can be selected.
π How to Build and Test the Change
build components/automate-ui && start_all_services
β Checklist
π· Screenshots, if applicable