formkit / tempo Goto Github PK
View Code? Open in Web Editor NEWπ Parse, format, manipulate, and internationalize dates and times in JavaScript and TypeScript.
Home Page: https://tempo.formkit.com
License: MIT License
π Parse, format, manipulate, and internationalize dates and times in JavaScript and TypeScript.
Home Page: https://tempo.formkit.com
License: MIT License
The following code will result in wrong time display.
The input is in UTC/Zulu time. The timezone shift occurs but the offset is not maintained and presented in the format.
format({
date: new Date('2024-02-16T11:00:00Z'),
format: 'YYYY-MM-DDTHH:mm:ssZ',
tz: "Europe/Stockholm"
})
Result:
2024-02-16T12:00:00+0000
i didn't find way to pass {numberingSystem:'arab'} , it's a valid option to intl.DateTimeFormatOptions
but i can include it in locale string like this ar-u-nu-arab
this throw invalid locale tag ar-u-nu-arab-u-hc-h12
error as format function already append hour cycle to the locale
possible solutions
-u-hc-h12
appended to locale and using hour12 and hourCycle options instesdCurrently if you try to use yearStart
or yearEnd
they will not compile in typescript, with the error:
Module '"@formkit/tempo"' has no exported member 'yearStart'.ts(2305)
It looks like it was implemented in: 8ae7a3b
But I'm not sure the types were added to the index.d.cts
file.
In the ye olde days, timezones were not standardized so the offset from GMT is basically the geographic position of the timezone in degrees/minutes.
So the timezone offset for America/Detroit
in 1904 is -05:32.18333333333334
, or 5 hours, 32 minutes, 11 seconds. Since timezone offsets (+-00:00
) cannot represent seconds 0.1.1
rounds these offsets to the nearest minute. -0532
.
However, this causes problems when performing bi-directional format/parse β if you parse a date at midnight in one of these timezones and then format it back you will lose 11 seconds of time and the date will actually be the day before at 11:49pm.
To solve this, we need to add a second or even milliseconds to our timezone format. Perhaps something like +-HH:mm:ss.SSS
with the ss.SSS
being optional should be supported.
The current validOffset code allows up to 39 hours and 69 minutes e.g. '+3969'. This is too wide, and makes the current validation incorrect.
The offsets being validated are Tempo defined offsets According to the documentation, these should be ISO 8601 compatible, and, according to the list of UTC offsets one only needs to go up to 15 hours and 45 minutes.
Current 'wide' validOffset implementation
export function validOffset(offset: striang) {
const valid = /^([+-])[0-3][0-9][0-6][0-9]$/.test(offset)
if (!valid) throw new Error(`Invalid offset: ${offset}`)
return offset
}
Hello, I am migrating away from MomentJS (finally) to your awesome library, however I'm having some issues with the a
or A
token. locally it shows as a.m.
(or P.M
for A
in evening) but in the CI the exact same unit tests are failing because the format outputs am
instead. Also what is a bit strange is that on the website, it shows as am
but I run my code locally it shows as a.m
.
I'm looking to get consistent result (I would prefer to always get am
and not a.m.
). I'm wondering if that difference is somehow coming from my locale setup? I'm in Canada in the Eastern TZ.
For example, with the format of 'YYYY-MM-DD hh:mm:ss a'
on the website I see '2024-05-04 11:53:12 pm'
but if I run it locally I see instead '2024-05-04 11:53:12 p.m.'
, why?
EDIT
Yeah after testing on MDN Intl.DateTimeFormat, the output is a.m.
for en-CA
but am
for en-US
. Are there any I can overwrite this behavior and always have the same result?
EDIT 2
ahh I found that I can pass en-US
as 3rd argument of either parse()
or format()
and now it shows the am
Different Topic (question)
Also on a different topic, in Moment they had the .utc()
function to mark the Date as UTC to differentiate local vs UTC date time. Are there any equivalent in Tempo? Below is an example taken from Moment's website
moment().format(); // 2013-02-04T10:35:24-08:00
moment.utc().format(); // 2013-02-04T18:35:24+00:00
I found that this might work, tzDate('2020-02-04', 'utc')
, is that the correct way to get UTC? It gives me 2020-02-04T00:00:00Z
We currently have sameDay
which is a helpful utility to compare two dates with reduced resolution, which I find helpful in many real-world applications. However, it would be nice to include a full range of these utilities:
We are looking to move from Date-fns to your package. However, currently when running the following
format(new Date(), "do MMMM yyyy")
from a server component we get the following Error: Invalid time zone specified: Etc/Unknown
When we run our NextJS app we run set TZ=UTC && next dev to emulate our server environments running against UTC
Would you consider adding a feature to set the default timezone that Tempo would use to format dates?
Perhaps deviceTZ()
could be enhanced to consult a default timezone override, falling back to the device timezone if unset?
@aleksandrjetβs work on #28 made me think it would be great to have an export size table on the docs, and perhaps the README.md that gets generated automatically on releases (could be generated on this github action).
would be nice to provide bi-directional duration formatting and parsing .. the behavior would be similar to Intl.DurationFormat
( still experimental )
Looks like the only option currently is "Z" for timezone offset (+0800).
Looking at Intl.DateTimeFormat['timezonename']
property, these could be useful:
z
: short generic (PT)zz
: short (PST)zzz
: long generic (Pacific Time)zzzz
: long (Pacific Standard Time)In case we are comparing with the current time, the second argument could be omitted.
It seems to work as expected, but it doesn't seem obvious from the docs.
It also causes a type error because the second argument is required.
Most likely, in functions other than is*
you can follow the same way and not write new Date()
in case the operation is performed with the current time.
Interesting project you have here!
I tried to filter the year from the "long" date style and expected it to look like March 30
but it rendered March 30,
(note the extra comma).
I wasn't sure if this was unavoidable, but I wanted to bring it to your attention.
format({
date: someDate,
format: {date: "long"},
partFilter: (part) => part.partName !== "year",
})
Relates to similar error found on #1.
Browser: Microsoft Edge Version 121.0.2277.113
For some reason tzDate()
is not being recognized.
tzDate is not a function
Same error further down the page.
Also noticed an error when viewing in Brazilian Portuguese (same browser, same version):
Date (terça-feira, 13 de fevereiro de 2024) does not match format (dddd, MMMM D, YYYY)
The current documentation uses the time 11:45, which doesn't change based on locale. However, if you used, say, 14:34, the examples would be more illustrative when used across locales that default to 12- versus 24-hour time renderings.
It seems to have a problem when parsing date in this format 2024-04-16T09:11:07+0000
. I got the following error :
Invalid offset: +0000
at (...node_modules\@formkit\tempo\src\parse.ts:111:18)
at Array.forEach ()
at Module.parse (...node_modules\@formkit\tempo\src\parse.ts:77:15)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
Hi, I'd like to request the possibility to explicitly work with milliseconds during the various operations this library offers. The uppercase S is a common template token for parsing and formatting milliseconds, with the ability to vary the number of decimal places using multiple S (e.g. .S
, .SS
, .SSS
).
Parsing a datetime with milliseconds already works when not using a custom format, for example parse("2022-08-03 16:56:54.477")
returns the appropriate date object 2022-08-03T14:56:54.477Z
.
Another thing I encountered is that tzDate
seems to remove the milliseconds part of the date, both tzDate("2022-08-03 16:56:54.477", "Europe/Berlin")
and tzDate(parse("2022-08-03 16:56:54.477"), "Europe/Berlin")
return 2022-08-03T14:56:54.000Z
.
Thanks for this library its a delight to use!
One feature I am missing is for a way to get the week number of a given date + startOfWeekDay.
Would be cool if this could also be included in the formatting tokens.
https://codepen.io/tiamed/pen/PogGXKj
format(new Date(), 'YYYY-MM')
should return '2024-03' but returned '2024-3'
Upgrading to version 0.0.14 caused the format function to malfunction.
I believe the issue lies within this piece of code.
// We need to apply an offset to the date so that it can be formatted as UTC.
tz ??= deviceTZ()
if (tz.toLowerCase() !== "utc") {
inputDateOrOptions = removeOffset(
inputDateOrOptions,
offset(inputDateOrOptions, tz, "utc")
)
}
The content of deviceTZ
is obtained from Intl.DateTimeFormat().resolvedOptions().timeZone
, and this function requires the TZ
environment variable to be set when executed in the local environment. If TZ is not set, deviceTZ
will return undefined, causing tz
to also become undefined, which results in an error when attempting to use tz.toLowerCase()
.
Also, if deviceTZ is undefined, tz needs to be specified in the FormatOptions, which means it can only be used in the FormatOptions pattern.
I think it would be beneficial to include a branching condition for cases where deviceTZ is undefined but tz is not set to UTC.
Due to the lack of PURE annotations, extra code is included in bundles. Example: var tokens = new Map(...)
is included and immediately thrown away (tokens
var is not used, but the bundler is not sure if new Map
can be safely omitted).
As I suppose tokens
is indeed pure, this issue can be fixed by adding a few /* @__PURE__ */
annotations like this:
Line 89 in 28a9539
export const tokens = /* @__PURE__ */ new Map(
/* @__PURE__ */ [...clockAgnostic, ...clock24, ...clock12].map((format) => {
return [format[0], format]
}),
)
More info:
Bundler βΒ vite 5.1.4
How to use as CDN?
thank you
Would love to see a "format relative time" helper, like date-fns
See: https://github.com/date-fns/date-fns/blob/f4e22da16/src/formatRelative/index.ts#L54
Hi I really like this new library, but for me to migrate to it I really need the functionality of manipulating dates.
Given two Dates:
D1 = 2010-06-09T15:32:00Z
D2 = 2010-06-09T11:32:00Z
It should return 4 hours (or eq. in days/min/sec)
I've read the documentation, but I apologize if my knowledge falls short.
(validOffset)
I've noticed that the format 1982-05-17T07:44:00+0900
works as expected, but when using 1982-05-17T07:44:00+09:00,
it leads to a format error stating Error: Invalid offset: +09:0
.
I apologize if my knowledge is lacking.
I would like to set specific months or dates (absolute values).
While I can manage with addXxx (relative values) by working hard on calculations, I would prefer to have setXxx if possible.
See: https://momentjscom.readthedocs.io/en/latest/moment/02-get-set/20-set/
While the browser functionality suffices and writing a bit of source code is all it takes, having it return an immutable Date is appreciated.
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/setHours
The formatting function in this library works by applying an offset between the target and local timezones to the input Date
object, then formatting that adjusted date object, which is technically representing a different moment in time. This causes problems when the resulting time lands in between a daylight saving time boundary, since there can be moments of time that are impossible to represent in certain timezones. For example, in American timezones, the time "March 10, 2024 at 2:30 AM" is impossible to represent, since the clocks jump from 1:59 AM to 3:00 AM. So the approach used by this library outputs an incorrect time around this boundary:
With this test script:
import { format } from '@formkit/tempo';
const date = new Date(Date.UTC(2024, 2, 10, 2, 30));
console.log(
'@formkit/tempo:',
format({
date,
format: { date: 'full', time: 'full' },
tz: 'UTC',
}),
);
console.log(
'Intl.DateTimeFormat:',
new Intl.DateTimeFormat('en-US', {
dateStyle: 'full',
timeStyle: 'full',
timeZone: 'UTC',
}).format(date),
);
The output with TZ=UTC
is correct:
@formkit/tempo: Sunday, March 10, 2024 at 2:30:00 AM +0000
Intl.DateTimeFormat: Sunday, March 10, 2024 at 2:30:00 AM Coordinated Universal Time
But the output with TZ=America/New_York
is incorrect:
@formkit/tempo: Sunday, March 10, 2024 at 3:30:00 AM +0000
Intl.DateTimeFormat: Sunday, March 10, 2024 at 2:30:00 AM Coordinated Universal Time
Hi! I am trying to use the diffMinutes helper and get the following error:
"The requested module '/node_modules/.vite/deps/@formkit_tempo.js?v=4f88df81' does not provide an export named 'diffMinutes' "
The import looks like this: import { addMinute, diffMinutes } from '@formkit/tempo'
Been using @formkit with Vue 3, composition API for a while on this project and it's the first time I've had the issue (just the addMinute
doesn't break it)
thank you!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.