Search code examples
javascriptangulardatetimetimezonedayjs

Angular: format date and skip timezones


How can I format date-time in Angular with DatePipe.format() & skip all timezone conversion regardless where I am. For example for such examples all over the world (regardless time) I want to get 07/06/2022:

console.log('2022-07-06T00:00:00.000Z :', this.datePipe.transform('2022-07-06T00:00:00.000Z', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T06:00:00.000Z :', this.datePipe.transform('2022-07-06T06:00:00.000Z', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T13:00:00.000Z : ', this.datePipe.transform('2022-07-06T13:00:00.000Z', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T23:59:59.000Z :', this.datePipe.transform('2022-07-06T23:59:59.000Z', 'MM/dd/yyyy', '+0000'), '\n\n');

console.log('2022-07-06T00:00:00-07:00 :', this.datePipe.transform('2022-07-06T00:00:00-07:00', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T06:00:00-07:00 :', this.datePipe.transform('2022-07-06T06:00:00-07:00', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T13:00:00-07:00 :', this.datePipe.transform('2022-07-06T13:00:00-07:00', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T23:59:59-07:00 :', this.datePipe.transform('2022-07-06T23:59:59-07:00', 'MM/dd/yyyy', '+0000'), '\n\n');

console.log('2022-07-06T00:00:00-12:00 :', this.datePipe.transform('2022-07-06T00:00:00-12:00', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T06:00:00-12:00 :', this.datePipe.transform('2022-07-06T06:00:00-12:00', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T13:00:00-12:00 :', this.datePipe.transform('2022-07-06T13:00:00-12:00', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T23:59:59-12:00 :', this.datePipe.transform('2022-07-06T23:59:59-12:00', 'MM/dd/yyyy', '+0000'), '\n\n');

console.log('2022-07-06T00:00:00+12:00 :', this.datePipe.transform('2022-07-06T00:00:00+12:00', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T06:00:00+12:00 :', this.datePipe.transform('2022-07-06T06:00:00+12:00', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T13:00:00+12:00 :', this.datePipe.transform('2022-07-06T13:00:00+12:00', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T23:59:59+12:00 :', this.datePipe.transform('2022-07-06T23:59:59+12:00', 'MM/dd/yyyy', '+0000'), '\n\n');

console.log('2022-07-06T00:00:00+07:00 :', this.datePipe.transform('2022-07-06T00:00:00+07:00', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T06:00:00+07:00 :', this.datePipe.transform('2022-07-06T06:00:00+07:00', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T13:00:00+07:00 :', this.datePipe.transform('2022-07-06T13:00:00+07:00', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T23:59:59+07:00 :', this.datePipe.transform('2022-07-06T23:59:59+07:00', 'MM/dd/yyyy', '+0000'), '\n\n');

console.log('2022-07-06T00:00:00+00:00 :', this.datePipe.transform('2022-07-06T00:00:00+00:00', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T06:00:00+00:00 :', this.datePipe.transform('2022-07-06T06:00:00+00:00', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T13:00:00+00:00 :', this.datePipe.transform('2022-07-06T13:00:00+00:00', 'MM/dd/yyyy', '+0000'), '\n\n');
console.log('2022-07-06T23:59:59+00:00 :', this.datePipe.transform('2022-07-06T23:59:59+00:00', 'MM/dd/yyyy', '+0000'), '\n\n');

all this examples should return 07/06/2022. I tried different approaches - but still can see issues.

The only way I found is a very dirty solution:

if (date?.match(/^\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])$/)) {
  return date.substring(5, 7) + '/' + value.substring(8, 10) + '/' + value.substring(0, 4);
}

Basically take string and parse values from it. I don't think it's a pretty way. Also I'm using dayjs and tried: dayjs(date).tz('Greenwich').format('MM/DD/YYYY');

How can I get the same date everywhere?


Solution

  • If all your inputs are strings in ISO 8601 date+time+offset format as you showed, then you can define a function to extract the offset from the string:

    const getOffset = (s) => s.match(/[+-]\d{2}:\d{2}$|Z$/)[0];
    

    This will (for example) return -07:00, +12:00 or Z from your input strings, which happen to be exactly the format that Angular's date pipe uses for its timeZone parameter.

    const input = '2022-07-06T00:00:00-07:00';
    const output = this.datePipe.transform(input, 'shortDate', getOffset(input));
    

    Note that I used shortDate here to avoid localization issues. I recommend you do the same.

    Alternatively, you could use Luxon, which has this built in:

    DateTime.fromISO(yourInputString, { setZone: true }).toLocaleString(DateTime.DATE_SHORT)
    

    The setZone option will automatically set time zone offset from the value in the string. Then, when you call toLocaleString (or any of the other many formatting functions provided by Luxon), the results will reflect the original input, without any time zone conversion.

    Also, you asked about using day.js for this. You can do so, but you would need to add logic to support keeping the zone when you parsed it, as that functionality is not built-in to day.js. See this issue.