11
votes

I'm using latest Angular 4 and Angular-Material2-2.0.0-beta7. This is my template using MdDatePicker:

<md-input-container fxFlex="33" class="birthday-container">
    <input mdInput name="birthday" placeholder="Birthday" required [(ngModel)]="member.birthday" [mdDatepicker]="birthdayPicker">
    <button mdSuffix [mdDatepickerToggle]="birthdayPicker"></button>
</md-input-container>
<md-datepicker #birthdayPicker></md-datepicker>

In app.module, here is the provider:

{provide: DateAdapter, useClass: NativeDateAdapter}

And member.birthday is Date type. But when JSON.stringify(member.birthday), it becomes one day before the selected date. For example:

Select 2017-4-1 from date picker, and the stringified result is 2017-03-31T13:00:00.000Z.

This post raised the same question but I'm not sure how to apply moment.js to the code.

6
What is the format you want the selected date in ? eg: DD-MM-YYYY for 01-04-2017 - Dhyey
Is your timezone -11:00? - RobG
Can you create a plunkr to reproduce - Aravind
@RobG My timezone is GMT+1000 (AEST) - Softhinker.com

6 Answers

3
votes

When we choose a date in the date picker, the selection is stored and manipulated in GMT (according to Greenwich timezone) time, but displayed back to the user in the formatted representation, taking into account user's current timezone. So stored and displayed dates are different (except of the users within timezone +0, like Greenwich).

When stringifying JS Date object, we get clear Greenwich timezone time, we can see it at https://time.is/GMT. What you probably expect to see is time representation formatted with your current timezone. See difference in my example.

// get current time
let date = new Date();
console.log('NATIVE JS DATE TIME', date.toString());
console.log('STRINGIFIED TIME', JSON.stringify(date));
console.log('FORMATTED TIME', `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`);

you can use very convenient moment's format() function for displaying date.

2
votes

I solved it by creating a custom date adapter (which inherits the native date adapter) and overriding create-date method to remove timezone offset

@Injectable({        providedIn: 'root' }) 
export class CustomDateAdapterService extends NativeDateAdapter {    
    public createDate(year: number, month: number, date: number): Date {
        const localDate = super.createDate(year, month, date);
        const offset = localDate.getTimezoneOffset() * 60000;
        return new Date(localDate.getTime() - offset); // utcDate
    } 
}

you can have a look at complete gist here

1
votes

One thing we need to understand how Date work. let me go through some example that how we can create a date object.

new Date('2020-08-22') // 22 aug 2020(your expect result)

the output of the above date depended on your time zone when you pass date like that it considers as GMT.it add offset according to your time zone. let's say you are in +0500 than it will print

Sat Aug 22 2020 05:00:00 GMT+0500

it adds 5h to your date.

if you are in -0500 so it will

Fri Aug 21 2020 19:00:00 GMT-0500

if you want Date always give you the date that you pass without adding offset.

new Date(2020,07,22)

Sat Aug 22 2020 00:00:00 GMT+0500

It not add an hour(offset) to a date object.

I just resolve the issue by the second approach and it's working for me.

0
votes

I am using PHP and SQL and I store the dates in the default format, like 2021-04-12 00:00:00. I want to store the actual value the user gave in, so I don't bother with converting time zones. It is irrelevant, when in the day the post was written I only want a good date representation.

This is why I store the given date's local time:

let phpDate = `${selectedDate.getFullYear()}-${selectedDate.getMonth()+1}-${selectedDate.getDate()} 00:00:00`;
// Notice that we have to add 1 to the zero-based JS month

Parse the stored date:

this.date = new Date(
        Number(d.substr(0, 4)),
        Number(d.substr(5, 2)) -1, // we need to subtract 1 because JS mont is 0-based
        Number(d.substr(8, 2)));
    })
0
votes

I hope this will help... just get the value of formgroup and store in const and reassign the value of formcontrol once used datePipe

import { DatePipe } from '@angular/common';

Just use the Datepipe in component.ts file and add in component providers and constructors

private datePipe: DatePipe,

providers: [DatePipe]

Inside the submit function

const commonForm = {
              ...this.pollAdd.value,
            };
            commonForm.endDate=this.datePipe.transform(this.pollAdd.value.endDate, 'yyyy-MM-dd');
            commonForm.startDate=this.datePipe.transform(this.pollAdd.value.startDate, 'yyyy-MM-dd');
-1
votes

use following conversion it will solve your problem .

  date =  new Date(this.moment(date).utcOffset('+0000').format('YYYY-MM-DD HH:MM'))