60

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?

Community
  • 1
  • 1
Matias Diez
  • 1,237
  • 2
  • 17
  • 26
  • what is your expected display format? – Aravind Jul 15 '17 at 18:59
  • The same one I'm using in the pipe: "dd/MM/yyyy" – Matias Diez Jul 15 '17 at 18:59
  • 1
    How about writing custom pipe and transforming the date to '1931-05-31T03:00:00.000+0000' , i.e. adding 3 hours. – Vega Jul 15 '17 at 20:59
  • 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 https://github.com/angular/angular/issues/9324. Your own, custom pipe (eg. based on moment.js) is probably a way to go. – Radosław Roszkowiak Jul 15 '17 at 21:01

7 Answers7

45

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

rzelek
  • 3,975
  • 1
  • 33
  • 35
  • Do you still recommend to use moment after your answer edit? – Patricio Vargas Nov 14 '18 at 21:32
  • 2
    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. – rzelek Nov 15 '18 at 10:53
  • 1
    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" – Patricio Vargas Nov 15 '18 at 18:18
  • 1
    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?/ – DoubleA Dec 06 '18 at 19:35
  • @DoubleA 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. – monty Mar 10 '19 at 21:42
  • Ex : (Datevalue, 'MMM d, y hh:mm a', '+0000') for GMT 0 – Nadeeshan Herath Dec 25 '20 at 03:47
  • @rzelek- sir can you tell me how to pass america/los_angeles in above pipe? – Kapil Soni Nov 26 '21 at 03:39
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'}}
Fateh Mohamed
  • 20,445
  • 5
  • 43
  • 52
  • 1
    This isn't manipulating the time for me. It still shows the same formatted date regardless of what I enter for the `"-120"` – Jeremy Thomas Mar 19 '19 at 13:53
  • 5
    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' – Orkun Tuzel May 01 '19 at 14:41
  • 1
    it also takes `UTC`, `UTC+1` etc – Aryeh Beitz Sep 08 '19 at 11:15
  • 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. – Ben Cheng Nov 09 '19 at 04:01
  • if timezone is UTC -6 then it should be {{ competition.compStart | date: 'short' : '-0600'}} if UTC 8:30 then {{ competition.compStart | date: 'short' : '0830'}} – XPowerDev May 04 '21 at 19:03
  • 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. – Adam Jan 13 '22 at 22:39
8

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)

Niranjana V S
  • 147
  • 2
  • 3
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));
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>
Hien Nguyen
  • 24,551
  • 7
  • 52
  • 62
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.

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>
Surya R Praveen
  • 3,393
  • 1
  • 24
  • 25