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

zonedTimeToUtc is not converting Utc time #174

Open
Frans-L opened this issue Mar 18, 2022 · 8 comments
Open

zonedTimeToUtc is not converting Utc time #174

Frans-L opened this issue Mar 18, 2022 · 8 comments

Comments

@Frans-L
Copy link

Frans-L commented Mar 18, 2022

It seems like that zonedTimeToUtc is not converting to UTC time, instead, it's converting to zoned time into your local time.

Here's an example, in which you try to convert something from your timezone to UTC. However, nothing is changed, since the zoned is the same as your local time.

So, it seems like zonedTimeToUtc should be called as zonedTimeToLocal.

import { zonedTimeToUtc } from "date-fns-tz";

const zonedTime = "2022-02-02T17:00:00.000Z";
const timezone = "Europe/Helsinki"; // YOUR TIMEZONE (e.g. Helsinki +2)

const org = new Date(zonedTime);
console.log("org", org.toISOString());
// output: 2022-02-02T17:00:00.000Z ✅

const converted = zonedTimeToUtc(zonedTime, timezone);
console.log("new", converted.toISOString());
// output: 2022-02-02T17:00:00.000Z ❌
// should be: 2022-02-02T15:00:00.000Z

Tested with:

  • date-fns: 2.28.0
  • date-fns-tz: 1.3.0
@marnusw
Copy link
Owner

marnusw commented Mar 25, 2022

Merits of function names aside, this is intended behaviour. When you are working with a zoned time you shouldn't be specifying that using a UTC time via an ISO string as you're doing, that defeats the purpose. Create a new date using the constructor directly, i.e. new Date(...), then pass that to zonedTimeToUtc with the time zone and you'll get the correct UTC date out.

Put another way, if you have the correct UTC time to start with, why use date-fns-tz at all?

@mPyth
Copy link

mPyth commented Apr 17, 2022

@marnusw : I have many problems with understanding what this f-on does.
Please, put somewhere in documentation what f-on does: it adds locale timezone offset and subtracts specified timezone offset to specified date. With this explanation misunderstanding will be impossible.

In order to be more clear I' suggestion next changes in documentation:

Current: Given a date and any time zone, returns a Date with the equivalent UTC time.
More precise: Given a date, any time zone and local time zone (as a third hidden param), returns a Date with the equivalent UTC time.

Current: (picked in any time zone)
More precise: (picked in whatever local time zone)

@neillindberg
Copy link

@marnusw I'm here because of material ui's x-datetime/picker. It is enforcing editing in a user's locale. What I'm building is a scientific app and it must be in UTC. So, I start with UTC, but the picker forces locale. I'm trying to override that back to UTC using date-fns-tz. I can't believe how much I'm struggling to do this. I thought, by the name of this function, that I had found a path forward. I can't believe this picker doesn't have a UTC or ISO flag.

@MrRainesE
Copy link

MrRainesE commented Nov 7, 2022

any update on this ?? facing the same issue:
expected: "2022-11-07T15:30:00.000Z"
result: Mon Nov 07 2022 16:30:00 GMT+0100 (Midden-Europese standaardtijd)
code below add in codesanbox

import * as React from "react";
import TextField from "@mui/material/TextField";
import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { DateTimePicker } from "@mui/x-date-pickers/DateTimePicker";
import { utcToZonedTime, zonedTimeToUtc } from "date-fns-tz";

export default function BasicDateTimePicker() {
const [value, setValue] = React.useState(
new Date("Mon Nov 07 2022 15:34:00 GMT+0100 (Midden-Europese standaardtijd)"));

return (
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DateTimePicker
ampm={false}
renderInput={(props) => <TextField {...props} />}
label="DateTimePicker"
value={value}
onChange={(newValue) => {
console.log(newValue,"\n", newValue.toISOString(),"\n", zonedTimeToUtc(newValue,
Intl.DateTimeFormat().resolvedOptions().timeZone ) );
setValue(newValue);
}}
/>
</LocalizationProvider>
);
}

@lamuertepeluda
Copy link

I agree that this function purpose is not understandable and the name is ambiguous. I though it was something useful to convert local dates to UTC, which is useful in several use cases...

Is there anything like that in date-fns?

@sopilkar
Copy link

sopilkar commented Oct 6, 2023

It looks like need to remove the latest "Z" from "zonedTime" string:

test('zonedTimeToUtc', () => {
    const zonedTime = '2022-02-02T17:00:00.000Z';
    const timezone = 'Europe/Helsinki'; // YOUR TIMEZONE (e.g. Helsinki +2)

    const converted = zonedTimeToUtc(zonedTime.replace('Z', ''), timezone);
    expect(converted.toISOString()).toEqual('2022-02-02T15:00:00.000Z');
  });

@richardoSGSI
Copy link

i'm also struggling with this, though my problem isn't exactly the same as OP

i'm trying to get the local EST date object and transform it to UTC

    const local = new Date();
    const utc = zonedTimeToUtc(local, "America/New_York");
    console.log("🚀 ~ file: AddModal.tsx:149 ~ handleSubmit ~ local:", local);
    console.log("🚀 ~ file: AddModal.tsx:150 ~ handleSubmit ~ utc:", utc);

output:

🚀 ~ file: AddModal.tsx:150 ~ handleSubmit ~ utc: Fri Feb 02 2024 20:03:59 GMT-0500 (Eastern Standard Time)
🚀 ~ file: AddModal.tsx:150 ~ handleSubmit ~ utc: Fri Feb 02 2024 20:03:59 GMT-0500 (Eastern Standard Time)

i'm pulling my hair out because of this. am i doing something wrong?

knime-github pushed a commit to knime/knime-js-pagebuilder that referenced this issue Nov 18, 2024
See the open issue here: marnusw/date-fns-tz#174

UIEXT-941 (Date&Time widget displays always browser timezone)
@pbaern
Copy link

pbaern commented Nov 19, 2024

I am pretty sure that this problem (the original problem as well as this) is related to #302.

I have been working around that other issue by recreating internal methods like so

import { toDate, type OptionsWithTZ } from "date-fns-tz";
// @ts-expect-error
import tzParseTimezone from "@@/node_modules/date-fns-tz/_lib/tzParseTimezone";
// @ts-expect-error
import tzPattern from "@@/node_modules/date-fns-tz/_lib/tzPattern";

export const fromZonedTime = (
  date: string | Date,
  timeZone: string,
  options?: OptionsWithTZ,
) => {
  if (typeof date === "string" && !date.match(tzPattern)) {
    return toDate(
      date,
      Object.assign(Object.assign({}, options), { timeZone }),
    );
  }
  date = toDate(date, options);
  const offsetMilliseconds = tzParseTimezone(timeZone, date);
  return new Date(date.getTime() + offsetMilliseconds);
};

export const toZonedTime = (
  date: string | Date,
  timeZone: string,
  options?: OptionsWithTZ,
) => {
  date = toDate(date, options);
  const offsetMilliseconds = tzParseTimezone(timeZone, date, true);
  return new Date(date.getTime() - offsetMilliseconds);
};

and with that also the problems above vanished.

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

9 participants