Giter VIP home page Giter VIP logo

Comments (12)

fturmel avatar fturmel commented on June 2, 2024 2

Spent some time this morning to understand the parse behavior with UTCDate previously discussed, and it's possible to make it work. You have to specify that the hours and minutes components are in UTC as well as using UTCDate. If no time zone information is part of the parse string, it will assume that your source string pattern is in the local time zone even if your reference date is a UTCDate. So I don't think the behavior is a bug necessarily, but it certainly requires a solid understanding of the internals to make sense of...

See specifically line 71, it will use the native Date to transpose to another time zone, but DateToSystemTimezoneSetter is only used if there are no other time zone related parsers to supersede it.

export class DateToSystemTimezoneSetter extends Setter {
priority = TIMEZONE_UNIT_PRIORITY;
subPriority = -1;
set<DateType extends Date>(date: DateType, flags: ParseFlags): DateType {
if (flags.timestampIsSet) return date;
return constructFrom(date, transpose(date, Date));
}
}

So, some solutions:

parse with UTCDate

import { UTCDate } from '@date-fns/utc';
import { parse } from 'date-fns';

const a = parse('00:00 Z', 'HH:mm X', new UTCDate(0));
const b = parse('00:00 Z', 'HH:mm X', new UTCDate(1970, 0));
const c = parse('00:00 Z', 'HH:mm X', new UTCDate('2024-01-07T17:06:30.545Z'));

console.log(a); // UTCDate 1970-01-01T00:00:00.000Z
console.log(b); // UTCDate 1970-01-01T00:00:00.000Z
console.log(c); // UTCDate 2024-01-07T00:00:00.000Z

Not sure of the actual problem you were trying to solve here, but if you're just trying to get the start of the day in UTC, here are some better options than using parse

startOfDay with UTCDate

import { UTCDate } from '@date-fns/utc';
import { startOfDay } from 'date-fns';

const a = startOfDay(new UTCDate(0));
const b = startOfDay(new UTCDate(1970, 0));
const c = startOfDay(new UTCDate('2024-01-07T17:06:30.545Z'));

console.log(a); // UTCDate 1970-01-01T00:00:00.000Z
console.log(b); // UTCDate 1970-01-01T00:00:00.000Z
console.log(c); // UTCDate 2024-01-07T00:00:00.000Z

native Date

const a = new Date(0);
a.setUTCHours(0, 0, 0, 0);

const b = new Date(Date.UTC(1970, 0));
b.setUTCHours(0, 0, 0, 0);

const c = new Date('2024-01-07T17:06:30.545Z');
c.setUTCHours(0, 0, 0, 0);

console.log(a.toISOString()); // 1970-01-01T00:00:00.000Z
console.log(b.toISOString()); // 1970-01-01T00:00:00.000Z
console.log(c.toISOString()); // 2024-01-07T00:00:00.000Z

from date-fns.

fturmel avatar fturmel commented on June 2, 2024 1

I'm going to close this issue, I think you have good options here. We can always re-open if needed.

from date-fns.

fturmel avatar fturmel commented on June 2, 2024

Those JS dates are not equivalent to each other.

  • new Date(0) is setting the timestamp offset from Jan 1st 1970 UTC
  • new Date(1970, 0) is Jan 1st 1970 in the system's local timezone

CleanShot 2024-01-06 at 08 34 03@2x

from date-fns.

Malix-off avatar Malix-off commented on June 2, 2024

@fturmel
That's what I showcased, indeed.
Then, why parse("00:00", "HH:mm", new Date(0)) and parse("00:00", "HH:mm", new Date(1970, 0)) outputs the same date?

from date-fns.

fturmel avatar fturmel commented on June 2, 2024

My bad, I see what you're saying.

date-fns operates on local time zones and you're printing out UTC so it's making it more confusing to understand. Both initial dates land on the same day in your local time zone since you're in a positive offset in relation to UTC (+1).

Compared to a negative offset (where in your example the parse function will return a different date):

America/New_York (-5)
new Date(0):       Wed Dec 31 1969 19:00:00 GMT-0500 (Eastern Standard Time)
new Date(1970, 0): Thu Jan 01 1970 00:00:00 GMT-0500 (Eastern Standard Time)

Europe/London (+1)
new Date(0):       Thu Jan 01 1970 01:00:00 GMT+0100 (Greenwich Mean Time)
new Date(1970, 0): Thu Jan 01 1970 00:00:00 GMT+0100 (Greenwich Mean Time)

You only parse "HH:mm" from your source string, so to build a complete Date object the parse function uses the reference date to complete the year, month, day (again, using the local timezone when interpreting this reference date).

from date-fns.

Malix-off avatar Malix-off commented on June 2, 2024

@fturmel ohkay, thanks for that clarification!
It would be nice to specify it in the docs, as it is a gotcha.
Also, don't you think it would be more intuitive to make the parse function to not take timezones into account for new Date(0)?
Otherwise, how to replicate this behavior?

from date-fns.

fturmel avatar fturmel commented on June 2, 2024

I was going to recommend that you look at the relatively new UTCDate wrapper to handle UTC operations, but I think there might be an issue here where the time zone still gets applied in the process...

@kossnocorp does this UTCDate + parse behavior look right to you? I assumed that parse('00:00', 'HH:mm', new UTCDateMini(0)) would return 1970-01-01T00:00:00.000Z.

import { UTCDateMini } from '@date-fns/utc';
import { parse } from 'date-fns';

function outputWithTimezone(tz, useNativeDate) {
  console.log(tz, '|', useNativeDate ? 'native Date' : 'UTCDateMini');

  process.env.TZ = tz;

  const DateClass = useNativeDate ? Date : UTCDateMini;

  const unix1 = new DateClass(0);
  const unix2 = new DateClass(1970, 0);

  console.log(unix1);
  console.log(unix2);

  const a = parse('00:00', 'HH:mm', unix1);
  const b = parse('00:00', 'HH:mm', unix2);

  console.log(a);
  console.log(b);
}

outputWithTimezone('America/New_York', true);
outputWithTimezone('Europe/London', true);
outputWithTimezone('America/New_York', false);
outputWithTimezone('Europe/London', false);

// America/New_York | native Date
// 1970-01-01T00:00:00.000Z
// 1970-01-01T05:00:00.000Z
// 1969-12-31T05:00:00.000Z
// 1970-01-01T05:00:00.000Z

// Europe/London | native Date
// 1970-01-01T00:00:00.000Z
// 1969-12-31T23:00:00.000Z
// 1969-12-31T23:00:00.000Z
// 1969-12-31T23:00:00.000Z

// America/New_York | UTCDateMini
// UTCDateMini 1970-01-01T00:00:00.000Z
// UTCDateMini 1970-01-01T00:00:00.000Z
// UTCDateMini 1970-01-01T05:00:00.000Z
// UTCDateMini 1970-01-01T05:00:00.000Z

// Europe/London | UTCDateMini
// UTCDateMini 1970-01-01T00:00:00.000Z
// UTCDateMini 1970-01-01T00:00:00.000Z
// UTCDateMini 1969-12-31T23:00:00.000Z
// UTCDateMini 1969-12-31T23:00:00.000Z

from date-fns.

fturmel avatar fturmel commented on June 2, 2024

@fturmel ohkay, thanks for that clarification! Don't you think it would be more intuitive to make the parse function to not take timezones into account for new Date(0)? Otherwise, how to replicate this behavior?

The native Date always stores its state as milliseconds since epoch. It doesn't matter how the object was initially constructed, and there's nothing persisted about the time zone either.

Date methods have UTC variants for UTC operations (which date-fns does not use).

For example (I'm in GMT -5):

CleanShot 2024-01-06 at 10 53 06@2x

Projects like date-fns-tz and UTCDate exist to bridge that gap.

If you're running this server-side, you could also set the TZ environment variable to UTC as I showed above or from the launch command export TZ=UTC && node index.js, but be aware of the possible side effects.

from date-fns.

Malix-off avatar Malix-off commented on June 2, 2024

I'm doing a library for a workaround of an issue with svelte runes, i'm checking the workaround for this current problem

from date-fns.

Malix-off avatar Malix-off commented on June 2, 2024

I did not found how to replicate that behavior with that code:

import { parse } from 'date-fns'

const unix = new Date(0);

console.log(unix);

/**
 * Consistently make this output "1970-01-01T00:00:00.000Z", no matter the timezone
 */
const date = parse("00:00", "HH:mm", unix);

console.log(date);

Can you help?

from date-fns.

fturmel avatar fturmel commented on June 2, 2024

How are you changing the time zone to test, and what's the runtime? (node, browser?)

If you ran export TZ=UTC && node index.js and kept that same terminal session open, TZ is probably still set to UTC.

import { parse } from 'date-fns';

function outputWithTimezone(tz) {
  process.env.TZ = tz;

  const unix = new Date(0);
  console.log(unix);

  const date = parse('00:00', 'HH:mm', unix);
  console.log(date);
}

console.log(process.env.TZ); // should be undefined unless set outside of node

outputWithTimezone('America/New_York');
// 1970-01-01T00:00:00.000Z
// 1969-12-31T05:00:00.000Z

outputWithTimezone('Europe/London');
// 1970-01-01T00:00:00.000Z
// 1969-12-31T23:00:00.000Z

from date-fns.

Malix-off avatar Malix-off commented on June 2, 2024

@fturmel

How are you changing the time zone to test, and what's the runtime? (node, browser?)

See

Debug information

  • date-fns version: 3.0.6
  • Browser/Node.js version: Google Chrome 120.0.6099.200 (Official Build) (64-bit)
  • Your timezone: GMT+0100 (Central European Standard Time)

I would want to make it so it's consistent across all env (including timezone), to basically always output the hour like if it was from Z (UTC).

from date-fns.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.