[#6688] added optional timezone identifier argument to the JSVM DateTime constructor
This commit is contained in:
parent
5d32d22ff5
commit
0efbbb0d10
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -1,6 +1,6 @@
|
||||||
## v0.27.0 (WIP)
|
## v0.27.0 (WIP)
|
||||||
|
|
||||||
- ⚠️ Moved the Create and Manage API rule checks out of the `OnRecordCreateRequest` hook finalizer, **aka. now all API rules are checked BEFORE triggering their corresponding `*Request` hook**.
|
- ⚠️ Moved the Create and Manage API rule checks out of the `OnRecordCreateRequest` hook finalizer, **aka. now all CRUD API rules are checked BEFORE triggering their corresponding `*Request` hook**.
|
||||||
This was done to minimize the confusion regarding the firing order of the request operations, making it more predictable and consistent with the other record List/View/Update/Delete request actions.
|
This was done to minimize the confusion regarding the firing order of the request operations, making it more predictable and consistent with the other record List/View/Update/Delete request actions.
|
||||||
It could be a minor breaking change if you are relying on the old behavior or have a Go `tests.ApiScenario` that is testing a Create API rule failure and expect `OnRecordCreateRequest` to be fired. In that case for example you may have to update your test scenario like:
|
It could be a minor breaking change if you are relying on the old behavior or have a Go `tests.ApiScenario` that is testing a Create API rule failure and expect `OnRecordCreateRequest` to be fired. In that case for example you may have to update your test scenario like:
|
||||||
```go
|
```go
|
||||||
|
@ -28,6 +28,15 @@
|
||||||
|
|
||||||
- Forced `text/javascript` Content-Type when serving `.js`/`.mjs` collection uploaded files ([#6597](https://github.com/pocketbase/pocketbase/issues/6597)).
|
- Forced `text/javascript` Content-Type when serving `.js`/`.mjs` collection uploaded files ([#6597](https://github.com/pocketbase/pocketbase/issues/6597)).
|
||||||
|
|
||||||
|
- Added optional timezone argument to the JSVM `DateTime` constructor to parse the date string in the specified TZ identifier in order to better handle the daylight saving time nuances ([#6688](https://github.com/pocketbase/pocketbase/discussions/6688)):
|
||||||
|
```
|
||||||
|
// the same as with CET offset: new DateTime("2025-10-26 03:00:00 +01:00")
|
||||||
|
new DateTime("2025-10-26 03:00:00", "Europe/Amsterdam") // 2025-10-26 02:00:00.000Z
|
||||||
|
|
||||||
|
// the same as with CEST offset: new DateTime("2025-10-26 01:00:00 +02:00")
|
||||||
|
new DateTime("2025-10-26 01:00:00", "Europe/Amsterdam") // 2025-10-25 23:00:00.000Z
|
||||||
|
```
|
||||||
|
|
||||||
- Soft-deprecated the `$http.send`'s `result.raw` field in favor of `result.body` that contains the response body as plain bytes slice to avoid the discrepancies between Go and the JSVM when casting binary data to string.
|
- Soft-deprecated the `$http.send`'s `result.raw` field in favor of `result.body` that contains the response body as plain bytes slice to avoid the discrepancies between Go and the JSVM when casting binary data to string.
|
||||||
(@todo update docs to use the new field)
|
(@todo update docs to use the new field)
|
||||||
|
|
||||||
|
|
|
@ -548,9 +548,18 @@ func baseBinds(vm *goja.Runtime) {
|
||||||
vm.Set("DateTime", func(call goja.ConstructorCall) *goja.Object {
|
vm.Set("DateTime", func(call goja.ConstructorCall) *goja.Object {
|
||||||
instance := types.NowDateTime()
|
instance := types.NowDateTime()
|
||||||
|
|
||||||
val, _ := call.Argument(0).Export().(string)
|
rawDate, _ := call.Argument(0).Export().(string)
|
||||||
if val != "" {
|
locName, _ := call.Argument(1).Export().(string)
|
||||||
instance, _ = types.ParseDateTime(val)
|
if rawDate != "" && locName != "" {
|
||||||
|
loc, err := time.LoadLocation(locName)
|
||||||
|
if err != nil {
|
||||||
|
loc = time.UTC
|
||||||
|
}
|
||||||
|
|
||||||
|
instance, _ = types.ParseDateTime(cast.ToTimeInDefaultLocation(rawDate, loc))
|
||||||
|
} else if rawDate != "" {
|
||||||
|
// forward directly to ParseDateTime to preserve the original behavior
|
||||||
|
instance, _ = types.ParseDateTime(rawDate)
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceValue := vm.ToValue(instance).(*goja.Object)
|
instanceValue := vm.ToValue(instance).(*goja.Object)
|
||||||
|
|
|
@ -568,15 +568,35 @@ func TestBaseBindsDateTime(t *testing.T) {
|
||||||
baseBinds(vm)
|
baseBinds(vm)
|
||||||
|
|
||||||
_, err := vm.RunString(`
|
_, err := vm.RunString(`
|
||||||
const v0 = new DateTime();
|
const now = new DateTime();
|
||||||
if (v0.isZero()) {
|
if (now.isZero()) {
|
||||||
throw new Error('Expected to fallback to now, got zero value');
|
throw new Error('(now) Expected to fallback to now, got zero value');
|
||||||
}
|
}
|
||||||
|
|
||||||
const v1 = new DateTime('2023-01-01 00:00:00.000Z');
|
const nowPart = now.string().substring(0, 19)
|
||||||
const expected = "2023-01-01 00:00:00.000Z"
|
|
||||||
if (v1.string() != expected) {
|
const scenarios = [
|
||||||
throw new Error('Expected ' + expected + ', got ', v1.string());
|
// empty datetime string and no custom location
|
||||||
|
{date: new DateTime(''), expected: nowPart},
|
||||||
|
// empty datetime string and custom default location (should be ignored)
|
||||||
|
{date: new DateTime('', 'Asia/Tokyo'), expected: nowPart},
|
||||||
|
// full datetime string and no custom default location
|
||||||
|
{date: new DateTime('2023-01-01 00:00:00.000Z'), expected: "2023-01-01 00:00:00.000Z"},
|
||||||
|
// invalid location (fallback to UTC)
|
||||||
|
{date: new DateTime('2025-10-26 03:00:00', 'invalid'), expected: "2025-10-26 03:00:00.000Z"},
|
||||||
|
// CET
|
||||||
|
{date: new DateTime('2025-10-26 03:00:00', 'Europe/Amsterdam'), expected: "2025-10-26 02:00:00.000Z"},
|
||||||
|
// CEST
|
||||||
|
{date: new DateTime('2025-10-26 01:00:00', 'Europe/Amsterdam'), expected: "2025-10-25 23:00:00.000Z"},
|
||||||
|
// with timezone/offset in the date string (aka. should ignore the custom default location)
|
||||||
|
{date: new DateTime('2025-10-26 01:00:00 +0200', 'Asia/Tokyo'), expected: "2025-10-25 23:00:00.000Z"},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let i = 0; i < scenarios.length; i++) {
|
||||||
|
const s = scenarios[i];
|
||||||
|
if (!s.date.string().includes(s.expected)) {
|
||||||
|
throw new Error('(' + i + ') ' + s.date.string() + ' does not contain expected ' + s.expected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -608,19 +608,27 @@ declare class Timezone implements time.Location {
|
||||||
interface DateTime extends types.DateTime{} // merge
|
interface DateTime extends types.DateTime{} // merge
|
||||||
/**
|
/**
|
||||||
* DateTime defines a single DateTime type instance.
|
* DateTime defines a single DateTime type instance.
|
||||||
|
* The returned date is always represented in UTC.
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
*
|
*
|
||||||
* ` + "```" + `js
|
* ` + "```" + `js
|
||||||
* const dt0 = new DateTime() // now
|
* const dt0 = new DateTime() // now
|
||||||
*
|
*
|
||||||
|
* // full datetime string
|
||||||
* const dt1 = new DateTime('2023-07-01 00:00:00.000Z')
|
* const dt1 = new DateTime('2023-07-01 00:00:00.000Z')
|
||||||
|
*
|
||||||
|
* // datetime string with default "parse in" timezone location
|
||||||
|
* //
|
||||||
|
* // similar to new DateTime('2023-07-01 00:00:00 +01:00') or new DateTime('2023-07-01 00:00:00 +02:00')
|
||||||
|
* // but accounts for the daylight saving time (DST)
|
||||||
|
* const dt2 = new DateTime('2023-07-01 00:00:00', 'Europe/Amsterdam')
|
||||||
* ` + "```" + `
|
* ` + "```" + `
|
||||||
*
|
*
|
||||||
* @group PocketBase
|
* @group PocketBase
|
||||||
*/
|
*/
|
||||||
declare class DateTime implements types.DateTime {
|
declare class DateTime implements types.DateTime {
|
||||||
constructor(date?: string)
|
constructor(date?: string, defaultParseInLocation?: string)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ValidationError extends ozzo_validation.Error{} // merge
|
interface ValidationError extends ozzo_validation.Error{} // merge
|
||||||
|
|
Loading…
Reference in New Issue