Data and Time Standardization In Angular Project

Overview

Angular is a popular framework for building mobile and web applications. Some Angular projects include several feature modules and components to manage. In one Angular project, we faced an issue regarding the date and time formats. The date and time formats varied throughout the project. Every feature module has two or three date formats displaying on the UI. At some places, we were using the moment javascript library to format the date. At several places, we were using Angular DatePipe to format. Showing different date and time formats in the UI seem absurd to the user. Suppose in one field we are showing date format as DD/MM/YY and another we are showing it as MM/DD/YY. So we got a requirement to standardize date and time throughout our application. If the user is selecting DD/MM/YY, it should be the same format for the date in all fields throughout the application. 

Data and Time Standardization

To standardize date and time format, refer Window date and time settings. In windows, if we navigate to Date and Time settings. We will see a link at the right side as Date, time and Regional Formatting. After that, we will get a link as Change date formats. In that screen, we will get drop-downs to select date and time formats as shown in the screenshot below. We will refer to all these formats and include them in our Angular project. Users will then have the flexibility to select the date and time format which will be shown throughout the project. 

















We will design the same kind of drop-downs shown above for the user. We will include all the formats shown in date and time settings.
We will design a component named user-profile. Let us see the same with an example. Go to the user-profile.component.html and write the below code for the dropdowns. We will use Angular Material dropdowns using <mat-select> and <mat-option> tags.
We will send the selected date and time formats to the back end on the click of the SAVE button. The back end API will be called to save the format in the database. The same date and time format will be returned in the GET API request after the user is logged in.

  <div class="container-fluid">
        <div class="row">
          <div class="col-md-8">
            <label for="timeFormat">Date Format</label>
            <mat-form-field>
              <mat-select [(value)]="dateFormat">
                <mat-option value="MM/DD/YYYY">MM/DD/YY (10/09/2019)</mat-option>
                <mat-option value="DD/MM/YYYY">DD/MM/YYYY (09/10/2019)</mat-option>
                <mat-option value="D/MM/YYYY">D/MM/YYYY (9/10/2019)</mat-option>
                <mat-option value="D/MM/YY">D/MM/YY (9/10/19)</mat-option>
                <mat-option value="DD/MM/YY">DD/MM/YY (09/10/19)</mat-option>
                <mat-option value="D/M/YY">D/M/YY (9/10/19)</mat-option>
                <mat-option value="DD/M/YY">DD/M/YY (09/10/19)</mat-option>
                <mat-option value="YYYY-DD-MM">YYYY-DD-MM (2019-09-10)</mat-option>
                <mat-option value="YY-DD-MM">YY-DD-MM (19-09-10)</mat-option>
                <mat-option value="DD-MMM-YY">DD-MMM-YY (09-Oct-19)</mat-option>
                <mat-option value="dddd, MMM D, YYYY">dddd, MMM D, YYYY (Wednesday, Oct 9, 2019)</mat-option>
                <mat-option value="MMM D, YYYY">MMM D, YYYY (Oct 9, 2019)</mat-option>
                <mat-option value="dddd, D MMM, YYYY">dddd, MMM D, YYYY (Wednesday, 9 Oct, 2019)</mat-option>
                <mat-option value="D MMM, YYYY">D MMM, YYYY (9 Oct, 2019)</mat-option>
              </mat-select>
            </mat-form-field>
          </div>
        </div>
        <div class="row">
          <div class="col-md-8">
            <label for="timeFormat">Time Format</label>
            <mat-form-field>
              <mat-select [(value)]="timeFormat">
                <mat-option value="HH:mm">HH:mm (15:45)</mat-option>
                <mat-option value="hh:mm A">hh:mm A (03:45 PM)</mat-option>
                <mat-option value="h:mm">h:mm (3:45)</mat-option>
                <mat-option value="HH:mm:SS">HH:mm:SS (15:45:11)</mat-option>
                <mat-option value="hh:mm:SS A">hh:mm:SS A (03:45:11 PM)</mat-option>
                <mat-option value="h:mm:SS A">h:mm:SS A (3:45:11 PM)</mat-option>
                <mat-option value="HH:mm:ss.ms">HH:mm:ss.ms (15:45:11.001)</mat-option>
                <mat-option value="hh:mm:ss.ms">hh:mm:ss.ms (03:45:11.001)</mat-option>
              </mat-select>
            </mat-form-field>
          </div>
        </div>
  <button (click)="onSubmitPreferences()" *ngIf="tabIndex==1" type="submit" mat-raised-button
    color="primary">SAVE</button>
      </div>

After this we will go to component.ts file where we will set the default format values and define the onSubmitPreferences() function to save the selected formats in the POST API request. 

Component({
  selector: 'app-user-profile',
  templateUrl: './user-profile.component.html',
  styleUrls: ['./user-profile.component.scss'],
})
export class UserProfileComponent implements OnInit {
  dateFormat = 'MM/DD/YYYY';
  timeFormat = 'hh:mm:SS A';
  constructor(
    private _userSrv: UserService,
    public authSrv: AuthService,
  ) {
    this.dateFormat = this.authSrv.dateFormat || this.dateFormat;
    this.timeFormat = this.authSrv.timeFormat || this.timeFormat;
  }

  ngOnInit() {
   }

  async onSubmitPreferences() {
    try {
      if (await this._userSrv.saveUserPref({ dateFormat: this.dateFormat, timeFormat: this.timeFormat })) {
       console.log("Success", "Preference saved");
        this.authSrv.loadPreferences();
      }
    } catch (e) {
      console.error(e);
      console.log("Error", "Error on preference save");
    }
  }
}

loadPreferences() function is the GET API request to get the saved date and time formats. saveUserPref() function is the POST API request to the back end. The payload will be the {dateFormat: this.dateFormat, timeFormat: this.timeFormat}.
Go to the UserService and write the functions as below:

  public getUserPref() {
    return this.http.get(url).toPromise();
  }

  public saveUserPref(data) {
    return this.http.post(url).toPromise();
  }

We have defined the loadPreferences() function in a different service. We need to load the date and time formats as soon as the user is logged in the application. So the loadPreferences() function is defined as below:

  async loadPreferences() {
    this.preference = await this._userService.getUserPref().then((res: any) => res.data);
    if (!this.preference) this.preference = {};
    this.dateFormat = this.preference.dateFormat || 'MM/DD/YYYY';
    this.timeFormat = this.preference.timeFormat || 'hh:mm:SS A';
    this.datetimeFormat = (this.preference.dateFormat + " " + this.preference.timeFormat) || 'MM/DD/YYYY hh:mm:SS A';
  }

We will pass the selected date and time formats to our custom pipe appDatePipe. We will convert the
display date, time or both using "Moment."
To use the selected date and time formats we will use the appDatePipe to show the date. We will go to some component where the date and time format is shown. let us first see the appDatePipe custom pipe.

import { Pipe, PipeTransform } from '@angular/core';
import * as moment from 'moment';

@Pipe({
  name: 'appDate'
})
export class AppDatePipe implements PipeTransform {

  transform(value: any, args?: any): any {
    if (!value) {
      return '';
    }
    if (!isNaN(value)) {
      return moment(new Date(value)).format((args || "MM/DD/YYYY"));
    }
    return moment(new Date(Date.parse(value))).format((args || "MM/DD/YYYY"));
  }
}


Now we will go to different components.html files and we will use the above-mentioned custom appDate pipe to show the standardize date and time format to the user. Now we user change the date and time format and click the SAVE button. The same date and time format will be saved in the back end. Whenever users will login we will call loadPreferences() function and get the saves time and date format. Then we will pass these formats to our custom pipe which will convert the given time into specified formats.

  <div>{{user.birthDate|appDate:authSrv.datetimeFormat}}</div>
  <div>{{user.birthDate|appDate:authSrv.dateFormat}}</div>
  <div>{{user.birthDate|appDate:authSrv.timeFormat)}}</div>

Comments