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

feat: enhance date formatting #428

Merged
merged 15 commits into from
Aug 17, 2024
Merged

feat: enhance date formatting #428

merged 15 commits into from
Aug 17, 2024

Conversation

WRXinYue
Copy link
Collaborator

@WRXinYue WRXinYue commented Aug 8, 2024

  • Added: timezone configuration option. For timestamps without time zones (e.g., 2004-06-16 00:00:00), the configuration can generate timestamps with time zones
  • Fixed: Resolved the issue where the browser needed to be refreshed when switching locale
  • Removed: formatTimestamp, and users are advised to create their own utility classes

When users utilize the formatDate function, it should be kept simple to avoid build failures caused by errors within formatDate. We should not restrict users' freedom in writing dates to increase migration costs. The related issues have been fixed, and the FAQ for this feature has been removed from the documentation.

If timezone is not set, the client's time zone will be used by default, which will not affect the current behavior.

The toDate function in date-fns-tz already implements new Date, so there is no need to create a new Date instance in vueRouter again.

Copy link

vercel bot commented Aug 8, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
valaxy-docs-dev ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 17, 2024 0:57am

@WRXinYue
Copy link
Collaborator Author

WRXinYue commented Aug 8, 2024

  • Using fromZonedTime may silently break users' expectations as it cannot parse dates that new Date() happily accepts, and a client-side error doesn't help as much as build-time warning / errors as they couldn't easily catch users' attention until the very page is visited.
  • Usages of new Date in fuse and rss aren't updated to use the new logic.
  • I suggest that we keep the note of derivation from YAML spec.
  • It will be good to have unit/E2E tests for different timezones

I'm sorry, but I can't understand why you say that new Date() cannot be parsed. As I mentioned before, toDate already includes new Date(), and even if the user passes in new Date(), no exceptions will occur. In the details of toDate, at this line of code:

if (
  argument instanceof Date ||
  (typeof argument === 'object' && Object.prototype.toString.call(argument) === '[object Date]')
) {

The date object is already handled. It's advisable to conduct your tests before making any comments. Regarding the fuse and rss, you raised valid points, but I believe these are considerations for the future. Currently, I haven't found any blogging frameworks that include these features. As for unit testing, since this is a simple and standalone feature, there's no need for me to create additional unit tests for date-fns-tz, as this would lead to unnecessary functionality. If you wish to test extensions of this feature, that would be a different matter altogether.

@WRXinYue
Copy link
Collaborator Author

WRXinYue commented Aug 8, 2024

toDate already includes new Date(), and even if the user passes in new Date(), no exceptions will occur
The date object is already handled. It's advisable to conduct your tests before making any comments.

Sorry for misconception, I was trying to mention the difference between fromZonedTime(string) and new Date(string), as toDate cannot correctly handle this date 2021-12-03 1:07:23 image

Case from https://github.com/Big-Cake-jpg/big-cake-jpg.github.io/blob/038c38296720590ae3c9403df9856af990fb2423/pages/posts/a-little-teacher.md?plain=1#L3

FWIW it silently breaks user expectations as date processing is completely handled at the client side, instead of crashing the build process, it's just making the problem harder to be found IMO.

Also FYI,

describe('frontmatter parse', async () => {
  it('page:time+8', () => {
    process.env.TZ = 'Asia/Shanghai'
    const utcDate = fromZonedTime('2023-07-19 10:55:53Z', cnTimezone)
    expect(formatInTimeZone(utcDate, cnTimezone, 'yyyy-MM-dd HH:mm:ss')).toEqual('2023-07-19 18:55:53')
  })

  it('page:time+0', () => {
    process.env.TZ = 'UTC'
    const utcDate = fromZonedTime('2023-07-19 10:55:53Z', cnTimezone)
    expect(formatInTimeZone(utcDate, cnTimezone, 'yyyy-MM-dd HH:mm:ss')).toEqual('2023-07-19 18:55:53')
  })
})

image

In the test case on page:time+0, although process.env.TZ is set to UTC, from a semantic perspective, the input cnTimezone in fromZonedTime('2023-07-19 10:55:53Z', cnTimezone) is the China timezone, which is inconsistent with the test objective. In your "2023-07-19 10:55:53Z" it is already a UTC date, as I mentioned before. Setting the timezone with an already passed UTC format is invalid. The second parameter of fromZonedTime might be used to define the initial timezone of the input time, not the target timezone. I suggest understanding the usage before making a submission. Additionally, the issue causing formatting failures due to passing special strings has been resolved, which is unrelated to whether strings are passed or not.

@BlueGlassBlock
Copy link
Contributor

BlueGlassBlock commented Aug 9, 2024

Setting the timezone with an already passed UTC format is invalid.

This is exactly what I'm trying to convey. formatDate yields incorrect result for dates that are already has timezone-awareness.

For example, formatDate('2021-12-07T11:00:00Z', 'yyyy-MM-dd HH:mm:ss', 'Asia/Shanghai)) with TZ='UTC' incorrectly yields '2021-12-07 03:00:00' instead of '2021-12-07 11:00:00', as fromZonedTime called toDate on it and applied Asia/Shanghai TZ on it forcibly - not within expectation. toDate(date, { timeZone }), by contrast, only applies timezone passed in when timezone is not present for the time string.

Aside from that, the formatDate implementation is incorrect withdate = formatISO(date). Internally, it calls toDate(date) and extracts different parts to form a ISO date string which is based on the environment (browser here) timezone, which effectively provided local timezone for every date without one, overriding other operation.

Copy link

vercel bot commented Aug 15, 2024

@WRXinYue is attempting to deploy a commit to the yunyoujun's projects Team on Vercel.

A member of the Team first needs to authorize it.

@YunYouJun
Copy link
Owner

If you're ready, please let me know.

@WRXinYue
Copy link
Collaborator Author

The code logic has been simplified. The handleTimeWithZone method performs the following operations. First, it converts a date object to a string because the luxon library's DateTime.fromISO method only accepts strings as input. If an object like new Date is passed in, new Date will internally generate a UTC timestamp. Calling DateTime.fromISO(date, { setZone: true }) will not affect dates that already have a timezone. For dates not parsed by DateTime.fromISO, if they are considered non-ISO 8601 format, they will be assumed to lack a timezone, and the system will add a default timezone based on the parameters provided by the user. Such operations can only be accomplished by luxon's DateTime. However, luxon cannot handle certain special date formats, such as 2021-12-03 1:07:23. Therefore, the format method from date-fns is used to manually format the date to 'yyyy-MM-dd\'T\'HH:mm:ss'.

@WRXinYue
Copy link
Collaborator Author

All test cases have passed. If there are no issues upon review, the merge can proceed.

@WRXinYue WRXinYue merged commit 49e8008 into YunYouJun:main Aug 17, 2024
9 checks passed
Copy link

Yun Good!

@YunYouJun
Copy link
Owner

#486

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

Successfully merging this pull request may close these issues.

3 participants