78

I'm setting up a mat-datepicker for DOB and traditionally the display format is MM/DD/YYYY,I need to change it to DD/MM/YYYY with less coding

I tried format tag in mat-date picker but it does not work,other date pickers like ngbDatepicker format can easily changed through one line of coding

  <div class="col-md-3 Dinline-block">
     <mat-form-field>
        <input matInput [matDatepicker]="picker2" [max]="currentDate" 
         placeholder="DOB(DD/MM/YYYY)" required formControlName="dob" 
          readonly />
        <mat-datepicker-toggle matSuffix [for]="picker2"></mat-datepicker- 
         toggle>
        <mat-datepicker #picker2></mat-datepicker>
     </mat-form-field>
  </div>

The date displayed after selecting from mat-date picker should be DD-MM-YYYY and when the retrieving the value from date picker it should also be in DD-MM-YYYY format

pjpscriv
  • 866
  • 11
  • 20
Zeeshan Chaudhary
  • 803
  • 1
  • 6
  • 9

15 Answers15

118

The easiest way is to change the locale:

Add the following to the providers section of your module:

{ provide: MAT_DATE_LOCALE, useValue: 'en-GB' }
pjpscriv
  • 866
  • 11
  • 20
progm
  • 2,782
  • 3
  • 14
  • 32
  • 5
    Better to know all options and gain more knowledge. Look at [official API docs](https://material.angular.io/components/datepicker/overview) and search for `Internationalization`. – hastrb Apr 21 '20 at 18:31
  • 6
    This will NOT correctly parse any inputs the user makes via text, see [this issue](https://github.com/angular/components/issues/14291) for more details (No plans to fix it) – Juanjo Martinez Oct 15 '21 at 11:45
  • If you want an answer which will get rid of the issue completely is this one https://stackoverflow.com/a/58189036/8665500 – ezhupa99 Feb 18 '22 at 14:49
35

First, bind the format to your mat-datepicker.

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

along with this you need to import and provide the modules.

import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material';
import { MomentDateModule, MomentDateAdapter } from '@angular/material-moment-adapter';
{ provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
{ provide: MAT_DATE_FORMATS, useValue: MY_FORMATS }

And in HTML follow this simply.

<mat-form-field>
    <input
        matInput
        [matDatepicker]="dp"
        placeholder="Some verbose datepicker"
        [formControl]="date"
    >
    <mat-datepicker-toggle matSuffix [for]="dp"></mat-datepicker-toggle>
    <mat-datepicker #dp></mat-datepicker>
</mat-form-field>
Community
  • 1
  • 1
miraclesInMe
  • 375
  • 3
  • 2
  • You need to add this code to whichever module you are working on. – jalpa Dec 17 '20 at 09:07
  • @miraclesInMine hi i am using SAME CUSTOM_DATE_FORMAT, how can we we get DatePicker date without timezone I need time "Sat Jan 08 2022 01:41:59 GMT+0500" without GMT +0500 any help will be appreciated – khizer Jan 07 '22 at 20:44
  • @khizer use yourDate.split('GMT')[0] . This may be coming way too late though – kplus Apr 19 '22 at 09:59
34

Full Guide on how to display and also parse the date on a custom format

  1. Install "@angular/material-moment-adapter" the version of you angular
    npm i @angular/material-moment-adapter@[your_angular_version] find the version

  2. Install "moment"
    npm i moment

  3. Create a configuration on how you want the date to be displayed and parsed.

const MY_DATE_FORMAT = {
  parse: {
    dateInput: 'DD/MM/YYYY', // this is how your date will be parsed from Input
  },
  display: {
    dateInput: 'DD/MM/YYYY', // this is how your date will get displayed on the Input
    monthYearLabel: 'MMMM YYYY',
    dateA11yLabel: 'LL',
    monthYearA11yLabel: 'MMMM YYYY'
  }
};
  1. Import these modules
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MomentDateAdapter } from '@angular/material-moment-adapter';
  1. Provide the new configuration
{ provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
{ provide: MAT_DATE_FORMATS, useValue: MY_DATE_FORMAT }

This answered is inspired by this anwer

ezhupa99
  • 1,838
  • 13
  • 18
  • 7
    This answer deserves much more attention. The most answers on this topic just cover on how to change the language of the picker and not the input format. I created this stackblitz in addition: https://stackblitz.com/edit/angular-wdrkzm?file=src/app/datepicker-overview-example.html – afcode Jun 30 '22 at 16:32
  • @afcode thank you for posting that stackblitz. I am struggling to see though, how that does not simply change the date format for any datepicker in the app. Is there a way to set a different date format for different elements? Eg. one for datepickers with timestamps and another for date pickers with just a date? It seems I can provide this in a component, so I guess it could be possible to have different components for date pickers of different formats, but is there a more elegant way? – Daniel Methner May 14 '23 at 12:14
32

use dateadapter from core

import { DateAdapter } from '@angular/material/core';

constructor(private dateAdapter: DateAdapter<Date>) {
    this.dateAdapter.setLocale('en-GB'); //dd/MM/yyyy

}

`

Raja Sekaran
  • 397
  • 4
  • 10
20

I got it working after combining some knowledge from various answers here, so I thought I'd consolidate what worked for me.

Angular 10:

In your module, import MAT_DATE_LOCALE and add it to providers:

import { MAT_DATE_LOCALE } from '@angular/material/core'

@NgModule({
  declarations: [...],
  imports: [...],
  exports: [...],
  providers: [
    { provide: MAT_DATE_LOCALE, useValue: 'en-GB' }
  ]
})

If you use a shared module to import material this will change all the formats of your datepickers across the site.

pjpscriv
  • 866
  • 11
  • 20
zing
  • 561
  • 3
  • 12
  • 3
    This will NOT correctly parse any inputs the user makes via text, see [this issue](https://github.com/angular/components/issues/14291) for more details (No plans to fix it) – Juanjo Martinez Oct 15 '21 at 11:46
15

Try this in the component you are using mat-datepicker

import { DateAdapter } from '@angular/material';

constructor(private dateAdapter: DateAdapter<Date>) {
    this.dateAdapter.setLocale('your locale'); 
}
barbsan
  • 3,418
  • 11
  • 21
  • 28
Leandro Q
  • 181
  • 1
  • 3
  • This approach equals to `{provide: MAT_DATE_LOCALE, useValue: 'en-GB'}` setting in providers array of module. The difference is your approach sets it at runtime using `.setLocale()` function. – hastrb Apr 21 '20 at 18:29
6

Solution 1: Either you can declare in your individual module/shared module or app.module.ts

providers: [
    { provide: MAT_DATE_LOCALE, useValue: 'en-GB' },
]

Solution 2:

import { DateAdapter } from '@angular/material';

constructor(private dateAdapter: DateAdapter<Date>) {
        this.dateAdapter.setLocale('your locale'); 
}

enter image description here

Abdullah
  • 2,393
  • 1
  • 16
  • 29
3

In case you want to have 100% control here is solution I came up with using date-fns all the way.

Component

export const MY_DATE_FORMATS = {
  parse: {
    dateInput: ["dd.MM.yyyy", "dd/MM/yyyy", "dd,MM,yyyy"], // to accept different input styles from user
  },
  display: {
    dateInput: "dd.MM.yyyy", // display format in input field
    monthYearLabel: 'yyyy MMMM',
    dateA11yLabel: 'MMMM d, y',//'LL',
    monthYearA11yLabel: 'MMMM yyyy'
  },
};

@Component({
  providers: [
    { provide: MAT_DATE_LOCALE, useValue: nb },
    { provide: DateAdapter, useClass: YourCustomDateAdapter },
    { provide: MAT_DATE_FORMATS, useValue: MY_DATE_FORMATS },
  ],
})

Adapter

I had to write my own adapter, because DateFnsAdapter use parseISO(), and that is not what I want. All I need to do is to override parsing.

@Injectable()
export class YourCustomDateAdapter extends DateFnsAdapter {

  //this parses date from input field
  override parse(value: any, parseFormat: string | string[]): Date | null {
    if (typeof value == 'string' && value.length > 0) {
      if (!parseFormat.length) throw Error('Formats array must not be empty.');

      for (const currentFormat of parseFormat) {
        const fromFormat = parse(value, currentFormat, new Date(), {locale: this.locale});

        if (this.isValid(fromFormat)) {
          return fromFormat;
        }
      }

      return this.invalid();
    } else if (typeof value === 'number') {
      return new Date(value);
    } else if (value instanceof Date) {
      return this.clone(value);
    }

    return null;
  }
}

Component

Last piece of puzzle is how to control output format from datepicker component. I prefer to use FormControl for the input field (it can be done also with ngModel + ngModelChanges if you like)

@Input() config: DateFormatOutputFNS = DateFormatOutputFNS["yyyy-mm-dd"];    
this.local_control.valueChanges.subscribe(v => {
    
      if (isValid(v)){ //to avoid sending output as user type into input field
        if (this.withinRange(v)){ // add you validation logic as you like
          this.control.setValue(format(v, this.config))
          this.control.markAsDirty()
          this.control.markAsTouched()
        }
      }

})

Config options

refer to this.config above. Add output format options as you like according to date-fns formats

export enum DateFormatOutputFNS {
  "yyyy-mm-dd" = "yyyy-MM-dd",
  "yyyy-mm-ddT00:00:00Z" = "yyyy-MM-dd\'T\'HH:mm:ss\'Z\'",
}
  • Thank you, this helped point in the right direction. I chose to also override the format() method in my "CustomDateAdapter extends NativeDateAdapter" instead of the valueChanges-listener in the component. – ccondrup May 04 '23 at 13:09
  • @Alexandr does this result in the output value to be not UTC, but whatever format you define in the parser? I find it weird that it is so difficult to tell mat-datepicker to output in a certain way. – Mattijs May 18 '23 at 04:17
  • @Mattijs yes, I needed the format to be exactly what I need to meet various definitions of date in open api 3. mat-datepicker as it is was not able to meet those. – Alexandr Tcacenco May 19 '23 at 09:05
2

For me, the best approach was to inject MAT_DATE_FORMATS to my component, which then dynamically determines what should the display format look like.

Setup in component:

  constructor(@Inject(MAT_DATE_FORMATS) private dateFormats) { }

  ngOnInit() {
    if (this.data.inputType === InputDateDialogRangeType.MonthAndYearOnly)
      this.dateFormats.display.dateInput = "MMMM YYYY";
    else if (this.data.inputType === InputDateDialogRangeType.YearOnly)
      this.dateFormats.display.dateInput = "YYYY";           
  }

Setup in module:

 providers: [
    { provide: MAT_DATE_FORMATS, useValue: MY_DATE_FORMAT },
    {
      provide: DateAdapter,
      useClass: MomentDateAdapter,
      deps: [MAT_DATE_LOCALE, MAT_MOMENT_DATE_ADAPTER_OPTIONS]
    },
    { provide: MAT_MOMENT_DATE_ADAPTER_OPTIONS, useValue: { useUtc: true } },

export const MY_DATE_FORMAT = {
  display: {
    dateInput: 'DD MMM YYYY',
    monthYearLabel: 'MMM YYYY',
    dateA11yLabel: 'LL',
    monthYearA11yLabel: 'MMMM YYYY',
  },
};
Robert J.
  • 2,631
  • 8
  • 32
  • 59
1

MomentDateAdapter v8.1.4 is working fine with my project running angular v12.2.0. However I was unable to use MomentDateAdapter versions ranging from 12.2 to 13.2. V8.1.4 seems to be working fine

heres the import array I used in my app module:

import { LOCALE_ID} from '@angular/core';
import {
    DateAdapter,
    MAT_DATE_FORMATS,
    MAT_DATE_LOCALE,
} from '@angular/material/core';
import { MomentDateAdapter } from '@angular/material-moment-adapter';

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

providers: [
        { provide: DateAdapter, useClass:MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
        { provide: MAT_DATE_FORMATS, useValue: DATE_FORMATS },
        { provide: LOCALE_ID, useValue: 'de-DE' }, // for German translation. Ignore this if not needed.
    ],
0

If you want to change the MaterialDatePicker date format into yyyy-mm-dd then use the below code. This code is working for me.

MaterialDatePicker<Long> materialDatePicker=materialDateBuilder.build();
materialDatePicker.addOnPositiveButtonClickListener(new MaterialPickerOnPositiveButtonClickListener<Long>() {
    @Override
    public void onPositiveButtonClick(Long selection) {
        // Get the offset from our timezone and UTC.
        TimeZone timeZoneUTC = TimeZone.getDefault();
        // It will be negative, so that's the -1
        int offsetFromUTC = timeZoneUTC.getOffset(new Date().getTime()) * -1;
        // Create a date format, then a date object with our offset
        SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
        Date date = new Date(selection + offsetFromUTC);

        mEt_last_date_to_apply.setText(simpleFormat.format(date));
    }
});

mEt_last_date_to_apply is my EditText

0

Angular 12 tested.

In the below chunk of code you can see how you can inject the datepipe into the constructor and then you can use it to convert date format in date controls. The best thing about this solution is that you are free to form the date as you wish regardless of any locale restrictions:

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

export class SomeComponent {

myDatepipe!: any;

constructor(private fb: FormBuilder, datepipe: DatePipe)
{
     this.myDatepipe = datepipe;
     this.someForm = this.fb.group({
         someDateControl : new FormControl()
         }); 
    
}

SomeAction()
{
 if(this.someForm.value.someDateControl)
    {
         const ConvertedDate = this.myDatepipe.transform(this.someForm.value.someDateControl, 'yyyy-MM-dd');
    }
}


}
Shadi Alnamrouti
  • 11,796
  • 4
  • 56
  • 54
  • 1
    if (this.dateFormControl.value) { const transformedDate = `${this.datePipe.transform(this.dateFormControl.value, 'yyyy/MM/dd')}`; this.dateFormControl.setValue(transformedDate); } I have tried this value is transformer but not reflected to Angular material date picker – khizer Nov 11 '21 at 23:42
0
import { DateAdapter } from '@angular/material/core';

 constructor( private dateAdapter: DateAdapter<Date>) {
    this.dateAdapter.setLocale('sv-se');
   
  }

enter image description here

Diego Venâncio
  • 5,698
  • 2
  • 49
  • 68
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Luciana Oliveira Jan 17 '23 at 17:35
-1

add to the providers list:

{provide: MAT_DATE_FORMATS, useValue: MY_FORMATS},
David Buck
  • 3,752
  • 35
  • 31
  • 35
bymw1990
  • 17
  • 3
-3
formatDate(Date(), "yyyy-MM-dd", 'en-GB')
Julian
  • 33,915
  • 22
  • 119
  • 174
Raja Sekaran
  • 397
  • 4
  • 10
  • 6
    Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Joe Ferndz Oct 12 '20 at 18:10