0

html:

            <mat-form-field>
                <input matInput [matDatepicker]="picker1" placeholder="From date: mm/dd/yyyy" name="from_date"
                       [(ngModel)]="callListRequestOb.from_date" maxlength="150">
                <mat-datepicker-toggle matSuffix [for]="picker1"></mat-datepicker-toggle>
                <mat-datepicker #picker1></mat-datepicker>
            </mat-form-field>

In method:

        this.callListRequestOb.from_date = new Date(this.callListRequestOb.from_date).toISOString().slice(0, 10);

When I select a date in datepicker it selects the date fine. But when I click the search button(I don't include it) the select time shows a behind date. I'm working on Angular 9. How do I solve this issue?

3
  • What happens when you do a .toLocaleDateString() instead of ISO? Commented Feb 8, 2021 at 13:20
  • Actually I need '2021-02-05T14:48:00.000Z' this type data to send header for API. That's why I use toISOString(). @MikeOne Commented Feb 8, 2021 at 13:40
  • We are just talking presentation here right? Converting it to something else when you submit is a different issue right? Commented Feb 8, 2021 at 15:40

6 Answers 6

7

Your selected date that results from the datepicker is in local time. From the documentation of toISOString() it becomes clear that this is UTC time.

"The timezone is always zero UTC offset, as denoted by the suffix "Z"." https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString

This difference can potentially result in a different day entirely if the local time initially was at 00:00:00 at night beginning of the day. By subtracting the timezone offset you can counter this.

const d = new Date(this.callListRequestOb.from_date)
// This will return an ISO string matching your local time.
new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes() - d.getTimezoneOffset()).toISOString();
Sign up to request clarification or add additional context in comments.

4 Comments

It was solved then but new problem arrives. Through selecting dates I've got data. Whenever I select pagination 2-3 times the dates changes. Because, it was selected GMT +6 first. But when I called that method 3-4 times that GMT +6 changes +12, +18 and so on. That's why datepicker date changes. Any solution? @Erik
d=> Thu Jan 28 2021 00:00:00 GMT+0600 (Bangladesh Standard Time) //1st call d=> Thu Jan 28 2021 06:00:00 GMT+0600 (Bangladesh Standard Time) //2nd call ...... and so on. After couple of times the datepicker date changes. @Erik
Is it possible to refactor the code in such a way that you only subtract the timezoneoffset once after selection and then reuse that date without changing it again? Or if that's not possible try to use the original input date for every call and not the altered one where you subtracted the timezoneoffset.
Erik you're a life saver, the code worked perfectly, thank you
1

This is probably a time zone issue, while posting data, I've selected date 14 on mat-datepicker and in payload, it's showing registrationDate:"2023-02-13T16:30:00.000Z"

So, I just created function

setDate(date:Date){
    let d=date;
    d.setHours(d.getHours() + 5);
    d.setMinutes(d.getMinutes() + 30);
    return new Date(d)
  }

Now, it's working fine, as it was 5:30 hrs behind the next date. I just added 5:30 hrs.

Comments

0

I fixed this easily with "string concatenation".

In the .component.html

<!-- date of birth -->
    <mat-form-field>
      <input matInput readonly [matDatepicker]="picker" placeholder="Date of birth" formControlName="dob" (dateChange)="formatDate($event)">
      <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
      <mat-datepicker #picker></mat-datepicker>
      <mat-error *ngIf="handleError('dob', 'required')">Date of birth is required</mat-error>
    </mat-form-field>

In the .component.ts

/* format date */
formatDate(e: any) {
  var d = new Date(e.target.value)
  var convertDate = d.toISOString().substring(0, 10) + d.toISOString().substring(10,);
  this.actorForm.get('dob')?.setValue(convertDate, { onlyself: true });
}

Comments

0

This is a timezone issue. If you console and see the time the date picker logs, you will see that it defaults to midnight (00:00:00) for any date selected. For time zones east of UTC, this works fine as it only requires adding a few hours to account for the time difference without changing the date. However, in time zones west of UTC, subtracting hours to adjust for the time difference unintentionally shifts the date by one day. Look at the function below that has a condition to handle the "off by one day" issue. You can call this function so that it runs when values of the date picker change.

const d = new Date();
const dateFieldSetter = () => {
  const adjustedTime = (d) => {
    if (d) {
      //prints the time zone offset, in minutes, between the local 
      //time zone and Coordinated Universal Time (UTC)
      console.log(getTimezoneOffset); 
    
      if (d.getTimezoneOffset() < 0) {
        d.setMinutes(d.getMinutes() - d.getTimezoneOffset());
      }
    }
    return d.toISOString().split('T').[0];
  };
};

Comments

0

solved it with moment adapter , angular 17

export const MY_FORMATS = {
  parse: {
    dateInput: 'YYYY-MM-DD',
  },
  display: {
    dateInput: 'DD/MM/YYYY',
    monthYearLabel: 'MMM YYYY',
    dateA11yLabel: 'LL',
    monthYearA11yLabel: 'MMMM YYYY',
  },
};

import {  MAT_DATE_LOCALE } from '@angular/material/core';
import { provideMomentDateAdapter } from '@angular/material-moment-adapter';
    
providers: [
       provideMomentDateAdapter(MY_FORMATS, {useUtc:true}),
       {provide: MAT_DATE_LOCALE, useValue: 'it-IT'}
]

read official docs material

Comments

0

This is proper solution for behind 1 day date problem in Angular:

onDateChange(event: MatDatepickerInputEvent<Date>): void {
    const selectedDate = event.value;
    if (selectedDate) {
        const d = new Date(selectedDate)
        const convertDate = new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes() - d.getTimezoneOffset()).toISOString();
        this.reminder_dateForm.get('reminder_date').setValue(convertDate, { onlyself: true });
    }
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.