I was working on the bug fix task, which aimed to solve an extraordinary issue at first sight. In the monolithic Angular-Spring application, I choose a specific date at the front end with an Angular calendar datepicker. However, the database suddenly saved one day before the initially selected date.
I started investigating the cause of the issue. First, I examined with Spring backend REST endpoint call with the breakpoint. The entity with the date was already coming incorrect from the Angular frontend. The backend endpoint on entry showed incorrect data, so the error was automatically not in the backend code.
At the frontend call for the backend REST endpoint, I also used JSON.stringify(object)
to check if the produced entity which was leaving the frontend to the backend was correct. What I found was that it was also already incorrect.
Consequently, the issue happened somewhere between the user browser and Angular call for the backend. In this way, I also eliminated the possibility that the problem was somewhere in the Spring JSON conversion library (I used Jackson).
In the end, I figured it out. The issue was in class, which was migrating datepicker form data into the object. While the Angular calendar datepicker collect the date from the browser also with local time zone as a string, data to JSON ware pushed as a JavaScript Date
class without a time zone. So if you, for example, pickup up any date, it was selected as the date for midnight with the timezone offset and transferred from string to Date
as the day before due the offset counted as date subtraction.
I was working in Central Europe. In the case of Central Europe (CET), where I was working, the browser records +1 hour from GMT in datepicker based on local PC time settings. So if I pick up the date, hours and minutes are selected for midnight (00:00). However, Date
class takes the datepicker string and subtract the negative offset from midnight and set a selected date for a day before.
This is the Angular’s datepicker component HTML code from the component form:
<div class="ui-g-6">
<div>
<label for="startDate">Start Date</label>
</div>
<vrm-form-field [control]="editForm.controls['startDate']">
<p-calendar id="startDate"
[formControlName]="'startDate'"
dateFormat="yy-mm-dd"
yearRange="1900:2100">
</p-calendar>
</vrm-form-field>
</div>
Following static function created an object from form datepicker which was pushed to REST endpoint before the fix:
static mapFromFormData(form: any) {
return new ImportantDate(form.startDate);
}
To fix the problem, I created a workaround. I made a Utility class with moment library
, which takes a datepicker string and select only required date information.
export class Utils {
public static formatDate(date: any): string {
if (date === undefined || date === null) {
return undefined;
} else {
return moment(date).format('YYYY-MM-DD');
}
}
}
You can see the implementation of the static Utils method, which fixed the date.
static mapFromFormData(form: any) {
return new ImportantDate(
Utils.formatDate(form.startDate)
);
}