Angular 4 date pipe displays wrong date because of time zones - how to fix this?
Asked Answered
D

8

61

I have a date value in each of my objects that I can Print like this:

<td> {{competition.compStart }}</td>

And here is how it looks:

1931-05-31T00:00:00.000+0000

In order to change the format to make it more readable I'm using the Angular date pipe:

<td> {{competition.compStart | date : "dd/MM/yyyy"}}</td>

With this result:

30/05/1931

As you can see, It is displaying the previous day (May 30 instead of May 31).

As far as I understand, the problem is related to the timezone, since I'm in Argentina and we have GMT-3 then 00:00 of the 31st minus 3 hours would be May 30 at 9 PM.

So how can I make it take the time literally and not process it based on the timezone, but still apply the format in the pipe?

Declass answered 15/7, 2017 at 18:50 Comment(5)
what is your expected display format?Leafstalk
The same one I'm using in the pipe: "dd/MM/yyyy"Declass
How about writing custom pipe and transforming the date to '1931-05-31T03:00:00.000+0000' , i.e. adding 3 hours.Tomb
What you are looking for does not seem to be currently possible with date pipe (but on the way), you can take a look at github.com/angular/angular/issues/9324. Your own, custom pipe (eg. based on moment.js) is probably a way to go.Outroar
It's crazy I need to write a custom pipe for this in Angular.Aleksandropol
P
46

Behind the scenes, DatePipe uses locale to display date in user's timezone. Try with client's timezone data:

1931-05-31T00:00:00.000-0300 instead of 1931-05-31T00:00:00.000+0000.

You can get client's offset in minutes using (new Date()).getTimezoneOffset()

This is actually the known issue/limitation of DatePipe. Community is aware of it. It the future, you will be able to specify timezone as one of parameters ({{ value | date:format:zone }}).

Here is the issue on github: https://github.com/angular/angular/issues/9324

For more advanced date manipulations, I recommend moment.js (less headaches, better consistency, less testing, simpler maintaining).

EDIT: It has been added:

date_expression | date[:format[:timezone[:locale]]]

Code: https://github.com/angular/angular/blob/5.0.4/packages/common/src/pipes/date_pipe.ts#L137 Docs: https://angular.io/api/common/DatePipe

Plimsoll answered 15/7, 2017 at 23:3 Comment(7)
Do you still recommend to use moment after your answer edit?Boehm
Moment is a very useful library, however, it is also quite big. If you can, stick to DatePipe only. I still recommend using moment for apps where you need to do a lot of manipulations on dates.Plimsoll
yes! that what everyone complains about...the size. Now one things you can't do with dataPipe is transform a date using e.g "Australia/Sydney" you have to pass a code like this "+4300"Boehm
I have the issue that when I'm using dates that were before daylight savings, it doesn't account for the extra hour. Using this command this.datePipe.transform("2018-11-01T00:00:00.000-04:00", 'MMMM yyyy', 'EST'), it calculates with -5 hours instead of -4 which is was at the time the date was recorded. Any ideas about how to get around this?/Huntingdon
@Huntingdon that's because EST is just a moniker for the -5 hour offset. You're still in the same boat as everyone else in the world and have to know the offset apriori. In your case you'd need to know the date-time was during daylight savings and then use EDT.Hemmer
Ex : (Datevalue, 'MMM d, y hh:mm a', '+0000') for GMT 0Adige
@rzelek- sir can you tell me how to pass america/los_angeles in above pipe?Sostenuto
A
10

for angular 5 and up , you can try to add timezone in pipe,

By default it takes the local timezone of user machine

and you can specify it in minutes for example for GMT-2, timezone: '-120'

{{ competition.compStart | date: 'short' : '-120'}}
Anderton answered 28/11, 2018 at 15:34 Comment(6)
This isn't manipulating the time for me. It still shows the same formatted date regardless of what I enter for the "-120"Topcoat
I was looking for an alternative to using currentDateTime.toUTCString() and this the date pipe that I used for dates for getting the same time: {{currentDateTime | date:'full':'GMT'}} The zone can take values like 'GMT', 'GMT+2' or 'EST'Andress
it also takes UTC, UTC+1 etcMyrica
For -120, it would help for date nigh saving. For example, in france. The timezone offset in sep and nov is different. i.e. the timezoneoffset of 2019-11-08 and 2019-08-08 is different.Ortrude
if timezone is UTC -6 then it should be {{ competition.compStart | date: 'short' : '-0600'}} if UTC 8:30 then {{ competition.compStart | date: 'short' : '0830'}}Estes
Is thee really no way to say "Use the date time as-is and do not convert to my local time zone"? E.g. for travel dates, the departure/arrival time is always local to that location, not where you are currently reading it from. I'e had many more problems over the years (in many languages) because everything thinks it knows best and converts to the time zone it thinks you want instead of just formatting the date i give it.Bimbo
B
9

In html file, the below:

{{ value | date:'yyyy-MM-dd hh:mm:ss a':'UTC'+ offset}}

In ts file add the following,

offset:number;
this.offset = (new Date().getTimezoneOffset());

can be useful for converting UTC time to system time (local)

Belittle answered 19/10, 2021 at 11:6 Comment(4)
this is the easiest solution i got. ThanksRhone
Sure All the best for future work @SuryaRPraveenBelittle
Your code has a typo. It should be {{ value | date:'yyyy-MM-dd hh:mm:ss a':'UTC'+offset}}. Please check the single quote. The right answer is 'UTC' +offset rather than 'UTC+offset'Gaga
@Gaga can you verify nowBelittle
B
1

I also faced the same problem. before saving data convert the date format to the one used in service.For example in my case in Java it was 'YYYY-MM-DD'.So in angular just before saving all the data: where birthdate is binded to your template field or is simply displayed.

this.birthdate= this.datePipe.transform(birthDate, 'yyyy-MM-dd'); where birthdate is not a date object but a string date.

Now, when you need to show the date on the UI use:

                let dd = (new Date(data.birthDate)).getUTCDate().toString();

                let mm = ((new Date(data.birthDate)).getMonth()).toString();
                let yy = (new Date(data.birthDate)).getFullYear().toString();

                this.birthDate = new Date(Number(yy), Number(mm), Number(dd));
Burdette answered 15/10, 2019 at 14:27 Comment(0)
T
1

I used Date pipe with offset in my project as below.

I shared for whom concern.

In component

this.offset = new Date().getTimezoneOffset();

In HTML file

<div>{{deviceInfo?.updatedAt | date: 'dd/MM/yyyy hh:mm:ss' : 'offset'}}</div>
Titoism answered 27/5, 2021 at 23:51 Comment(0)
P
1

See here for an additional solution. Specifying the date formatting as UTC solved my issue and I reference it now in the hopes that it will help others.

Permittivity answered 13/4, 2023 at 21:19 Comment(0)
R
0

Created a Custom Date pipe

import { DatePipe } from '@angular/common';
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'localizedDate',
})
export class LocalizedDatePipe implements PipeTransform {
  transform(value: any, locale: any, zone: any): any {
    var datePipe = new DatePipe(locale);

    var newDate = new Date(value);
    value = newDate.toUTCString(); // GMT

    if (locale == 'en-US' || locale == 'es-US') {
      value = datePipe.transform(value, 'MMM d, y', 'UTC');
    } else {
      value = datePipe.transform(value, 'd MMM y', 'UTC');
    }
    return value.replace('.', '').replace('.', '');
  }
}

HTML

<div *ngIf="{ locale: locale$ | async } as vm">
  <div class="card-publish-date">
    {{ item.publishedDate | localizedDate: vm.locale?.code:'UTC' | titlecase }}
  </div>
</div>
Rhone answered 6/2, 2023 at 17:55 Comment(0)
M
0

I think its worth to mention that you now have "DATE_PIPE_DEFAULT_OPTIONS" that can easily be added to app.module.ts.

providers: [
    {provide: DATE_PIPE_DEFAULT_OPTIONS, useValue: {timezone: 'UTC+2'}},
]

This will make all the dates printed with | date : 'short' be in the given timezone globally.

Musicianship answered 22/5 at 10:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.