Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] dayjs.tz do nothing #1965

Closed
lilonghe opened this issue Jun 28, 2022 · 23 comments
Closed

[BUG] dayjs.tz do nothing #1965

lilonghe opened this issue Jun 28, 2022 · 23 comments

Comments

@lilonghe
Copy link

lilonghe commented Jun 28, 2022

Describe the bug

moment.tz("2022-06-13T13:47:25Z", "America/New_York").format('YYYY-MM-DD HH:mm') -> 2022-06-13 09:47
dayjs.tz("2022-06-13T13:47:25Z", "America/New_York").format('YYYY-MM-DD HH:mm') -> 2022-06-13 13:47
dayjs.tz("2022-06-13T13:47:25Z", "Asia/Tokyo").format('YYYY-MM-DD HH:mm') -> 2022-06-13 13:47

Expected behavior
dayjs.tz look like do nothing

Information

  • Day.js Version dayjs.org site console
@kravorkid
Copy link

@lilonghe Hello have you initialized dayjs like the exemple below before using it ?

var utc = require('dayjs/plugin/utc')
var timezone = require('dayjs/plugin/timezone')
dayjs.extend(utc)
dayjs.extend(timezone)

@lilonghe
Copy link
Author

@kravorkid Yes, of course, and u can try run this code, it is useful:

dayjs.tz.setDefault("America/New_York")
dayjs("2022-06-13T13:47:25Z").tz().format('YYYY-MM-DD HH:mm') -> 2022-06-13 09:47

@kravorkid
Copy link

@lilonghe it's look like the dayjs.tz()... works differently from moment.tz the doc should be more explicit about this i've struggle a lot with those recently, the dayjs.tz() only parse the date to a timezone date without changing the given hours and minutes. when you look at the formatted string you see the +09:00 added to the current date whereas dayjs(date).tz(timezone) format automatically the date see differences below :

dayjs.tz('2022-06-13T13:47:25Z', 'America/New_York').format(), // "2022-06-13T13:47:25-04:00"
dayjs.tz('2022-06-13T13:47:25Z', 'Asia/Tokyo').format(), // "2022-06-13T13:47:25+09:00"

dayjs('2022-06-13T13:47:25Z').tz('America/New_York').format(), // "2022-06-13T09:47:25-04:00"
dayjs('2022-06-13T13:47:25Z').tz('Asia/Tokyo').format() // "2022-06-13T22:47:25+09:00"

@lilonghe
Copy link
Author

lilonghe commented Jun 30, 2022

@kravorkid
emmm, Ok, it's so weird. Maybe change the doc can help more people.
Time Zone
in this link, two different usage seems to be the same, but actually different.

dayjs.extend(utc)
dayjs.extend(timezone)

dayjs.tz("2014-06-01 12:00", "America/New_York")
dayjs("2014-06-01 12:00").tz("America/New_York")
dayjs.tz("2014-06-01 12:00", "America/New_York").format() -> 2014-06-01T12:00:00-04:00
dayjs.tz("2014-06-01 12:00", "America/New_York").format("YYYY-MM-DD HH:mm") -> 2014-06-01 12:00
dayjs("2014-06-01 12:00").tz("America/New_York").format() -> 2014-06-01T00:00:00-04:00
dayjs("2014-06-01 12:00").tz("America/New_York").format("YYYY-MM-DD HH:mm") -> 2014-06-01 00:00

@kravorkid
Copy link

@iamkun @sxzz is this the intented behavior of dayjs.tz("2014-06-01 12:00", "America/New_York") or is this a real bug and both dayjs().tz() and dayjs.tz() should give the same result ?
If so will it be fixe in dayjs 2.0 ?

@BePo65
Copy link
Contributor

BePo65 commented Jul 9, 2022

IMO this is a documentation topic:
dayjs.tz has 2 'modes' - parsing and converting.

dayjs.tz('2022-06-13T13:47:25Z', 'America/New_York')
Parsing parses the date string (evaluating a given timezone - in your example 'Z') and setting the timezone of the result to the given timezone ('America/New_York').
==> 2022-06-13 13:47 -04:00

dayjs('2022-06-13T13:47:25Z').tz('America/New_York')
Converting parses the date string (evaluating a given timezone - in your example 'Z') and converting the result to the given timezone ('America/New_York').
==> 2022-06-13 09:47 -04:00

I already created a pr for making the documentation for this feature more clearly.

@nimrodyanai
Copy link

I do not believe this is an issue with documentation.
I keep getting incorrect time-zone dates whatever code I use.
I am trying to get the date in zone "America/Bogota", but whatever I do, I keep getting the date in UTC +0. The zone is just ignored completely no matter how I write the code, so the date is always one day earlier than the input date.

@kravorkid
Copy link

kravorkid commented Jul 21, 2022

@nimrodyanai can you give me some exemple, and what do you want to achieve, maybe i could help on something, for now i've tried something very simple and it seems that it gave me the good UTC-0500 look at the code below :

const test = {
  parsing: dayjs.tz(dayjs(), 'America/Bogota').format(), //  Parsing the current date "2022-07-21T04:19:12-05:00"
  converting: dayjs().tz('America/Bogota').format()  // Converting the current date "2022-07-21T04:19:12-05:00"
}
console.log(test)

@nimrodyanai
Copy link

Here you go:

const convertDate = (date,format,zone) => {
  //var newDate = dayjs(date,format).tz(zone);
  var newDate = dayjs(date,format,zone);
  //newDate = newDate.$d.tz(zone,true);
  console.log(newDate);
  //var test = new Date(new Date (newDate).toLocaleString("es-CL", {timezone:zone}));
  return newDate;
}

I also tried to use the default timezone.
Here is what I am getting:
var newDate = dayjs("22-FEB-02","DD-MMM-YY","America/Bogota"); -> 2002-02-21T22:00:00.000Z

As you can see, the result is a day earlier than expected, and no matter how I test it, I always get this result.
This doesn't seem to be just a print issue - the incorrect date is sent to our system, so it's not a conversion done on the spot.

What I expected to get was "2002-02-22T22:00:00.000Z".

@kravorkid
Copy link

kravorkid commented Jul 21, 2022

@nimrodyanai Try this instead

dayjs.tz('2022-02-02', 'America/Bogota').format('DD-MM-YYYY') //  return 02-feb.-2022 raw format 2022-02-02T00:00:00-05:00 

@nimrodyanai
Copy link

nimrodyanai commented Jul 21, 2022

Some confusion here. The format is the input format, which is DD-MMM-YY. I need the output in standard ISO.
Based on your reply, I tried the following:
var newDate = dayjs.tz(date,format,zone).format();
But the result is the same, one day too early:

Input: 28-JAN-03
Output: 2003-01-27T22:00:00-05:00

@BePo65
Copy link
Contributor

BePo65 commented Jul 24, 2022

This time your problem comes from the fact that you just throw a date string to dayjs, hoping that the result wil be what you expect 😄 .

According to the documentation, dayjs expects an ISO8601 string as input and 28-JAN-03 definitely is not an ISO 8601 date string.
As a fallback, dayjs uses the javascript Date object initializer to parse the given date. If the utc plugin is loaded, then dayjs will fix the parsed date and add the offset of the current timezone.

So just use customParseFormat plugin if you want to parse a non ISO8601 date.

@nimrodyanai
Copy link

That same documentation also says that if I am using anything other than ISO8601, I should use the string+format option, which is what I was trying to do. I have tried the customParseFormat plugin as well as numerous other solutions with the timezone options, none of them work correctly.
The customParseFormat is actually the worst of the solutions, because it doesn't even recognize the string as a date even when I put the format in:

import dayjs from 'dayjs';
import customParseFormat from 'dayjs/plugin/customParseFormat.js';
dayjs.extend(customParseFormat);
var newDate = dayjs("22-FEB-02","DD-MMM-YY",true); //OR var newDate = dayjs("22-FEB-02","DD-MMM-YY"); OR var newDate = dayjs("22-FEB-02","DD-MMM-YY","es-CL"); OR var newDate = dayjs("22-FEB-02","DD-MMM-YY", "es"); I tried them all
console.log(newDate);
--> Result:
M {
  '$L': 'en',
  '$u': undefined,
  '$d': Invalid Date,
  '$y': NaN,
  '$M': NaN,
  '$D': NaN,
  '$W': NaN,
  '$H': NaN,
  '$m': NaN,
  '$s': NaN,
  '$ms': NaN
}

And for testing:
console.log(dayjs(date,format).isValid()); // --> result: false

@BePo65
Copy link
Contributor

BePo65 commented Jul 24, 2022

The problem is using 'MMM' in customParseFormat with locale 'en' as there is no definition for 'monthShort' in this locale and the documentation says you don't need monthShort in locale en. I will try to find out why we don't need monthShort in 'en' - give me a few days.

@nimrodyanai
Copy link

I tried converting the dates so that the format is DD-MM-YY as you suggested, but the result is always the same:

import customParseFormat from 'dayjs/plugin/customParseFormat.js';
dayjs.extend(customParseFormat);
import utc from 'dayjs/plugin/utc.js';
dayjs.extend(utc);
import timezone from 'dayjs/plugin/timezone.js';
dayjs.extend(timezone);
var newDate = dayjs.tz("19-02-00","DD-MM-YY","America/Bogota").$d;
console.log(newDate); // --> result: 2000-02-18T22:00:00.000Z

It's as if the zone parameter is just ignored and there is no way to convert it.

@BePo65
Copy link
Contributor

BePo65 commented Aug 4, 2022

In your code you use the internal variable $d of the dayjs object. Why do you do this?

A better variant of your code sample could look like this:

import customParseFormat from 'dayjs/plugin/customParseFormat.js';
import utc from 'dayjs/plugin/utc.js';
import timezone from 'dayjs/plugin/timezone.js';

dayjs.extend(customParseFormat);
dayjs.extend(utc);
dayjs.extend(timezone);

var newDate = dayjs.tz("19-02-00","DD-MM-YY","America/Bogota");
console.log(newDate.format()); // --> result: 2000-02-19T00:00:00-05:00

For me this looks like what you expected; am I right?

@nimrodyanai
Copy link

The reason I am using $d is that the object I get back from dayjs is not a date or even a string with the date. The date is inside the object under the $d variable.

@BePo65
Copy link
Contributor

BePo65 commented Aug 4, 2022

Oh no that is not the idea of internal variables 😄

dayjs(...) returns a dayjs object with many nice fields and functions. So if you want to get a string representation of a dayjs object, you just use the format(...) function of that object. The details can be found in the documentation - but of course you know that already.

@nimrodyanai
Copy link

That works!
I'm a bit surprised it doesn't work when the format is DD-MMM-YY, I had to manually transform MMM to MM to get it to work.
Any idea why that is? I thought dayjs was supposed to support custom formats...

@BePo65
Copy link
Contributor

BePo65 commented Aug 11, 2022

I suppose by

it doesn't work when the format is DD-MMM-YY

you mean 'using MMM when parsing a string to a date'.

To use MMM in parsing, you have to add the customParseFormat plugin - but perhaps sometimes the documentation is a little bit overwhelming. The list of parsing tokens that are made accessible by this plugin can be found in the section 'String + Format'.

@nimrodyanai
Copy link

I suppose by

it doesn't work when the format is DD-MMM-YY

you mean 'using MMM when parsing a string to a date'.

To use MMM in parsing, you have to add the customParseFormat plugin - but perhaps sometimes the documentation is a little bit overwhelming. The list of parsing tokens that are made accessible by this plugin can be found in the section 'String + Format'.

I tried using that plugin, and MMM is one of the available formats in the documentation. It even shows the short names in the example exactly as I input them in the string.

In the solution you suggested, the plugin actually exists and is called upon.
If I use the exact same code but with DD-MMM-YY as the format (and the input string), it doesn't work. If I convert the MMM to MM instead via code that translates the short names into numbers, it starts working.

I both cases I am parsing a string to a date. The only difference is that one time the string for example is 24-02-05 and in the other its 24-FEB-05 (and the expected format changes accordingly, of course).

@BePo65
Copy link
Contributor

BePo65 commented Aug 12, 2022

Here my updated test code:

import customParseFormat from 'dayjs/plugin/customParseFormat.js';
import utc from 'dayjs/plugin/utc.js';
import timezone from 'dayjs/plugin/timezone.js';

dayjs.extend(customParseFormat);
dayjs.extend(utc);
dayjs.extend(timezone);

const newDate = dayjs.tz('19-Feb-00', 'DD-MMM-YY', 'America/Bogota')
console.log(newDate.format()) // --> result: '2000-02-19T00:00:00-05:00'
console.log(newDate.format('DD-MMM-YY') // --> result: '19-Feb-00'

Is this what you need?

@nimrodyanai
Copy link

Yes, thank you! That works great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants