Skip to content

Commit 018f979

Browse files
committed
Added step for dateProxy
1 parent 8063377 commit 018f979

File tree

6 files changed

+118
-14
lines changed

6 files changed

+118
-14
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
- `dateProxy` now has a `step` option, to support seconds (when [not divisible by 60](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/time#using_the_step_attribute)).
1213
- [SuperDebug](https://superforms.rocks/super-debug) now opts out of runes mode as default.
1314

1415
### Fixed
1516

17+
- Fixed `dateProxy` for `time` formats, previously it returned an invalid date. If you only care about the time part in the date, use `time-utc` as format to avoid timezone changes.
1618
- Vite 6 bundling fixed by introducing a `default` field into exports in package.json.
1719

1820
### Changed

src/lib/client/proxies.ts

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,13 @@ type DefaultOptions = {
5050
empty?: 'null' | 'undefined' | 'zero';
5151
initiallyEmptyIfZero?: boolean;
5252
taint?: TaintOption;
53+
step: number;
5354
};
5455

5556
const defaultOptions = {
5657
trueStringValue: 'true',
57-
dateFormat: 'iso'
58+
dateFormat: 'iso',
59+
step: 60
5860
} satisfies DefaultOptions;
5961

6062
///// Proxy functions ///////////////////////////////////////////////
@@ -99,12 +101,14 @@ export function dateProxy<T extends Record<string, unknown>, Path extends FormPa
99101
format?: DefaultOptions['dateFormat'];
100102
empty?: Exclude<DefaultOptions['empty'], 'zero'>;
101103
taint?: TaintOption;
104+
step?: number;
102105
}
103106
) {
104107
return _stringProxy(form, path, 'date', {
105108
...defaultOptions,
106109
dateFormat: options?.format ?? 'iso',
107-
empty: options?.empty
110+
empty: options?.empty,
111+
step: options?.step ?? 60
108112
}) as CorrectProxyType<Date, string, T, Path>;
109113
}
110114

@@ -289,7 +293,13 @@ function _stringProxy<T extends Record<string, unknown>, Path extends FormPaths<
289293

290294
if (type == 'string') return stringValue;
291295
else if (type == 'boolean') return !!stringValue;
292-
else if (type == 'date') return new Date(stringValue);
296+
else if (type == 'date') {
297+
if (stringValue.indexOf('-') === -1) {
298+
const utc = options.dateFormat.indexOf('utc') >= 0;
299+
const date = utc ? UTCDate(new Date()) : localDate(new Date());
300+
return new Date(date + 'T' + stringValue + (utc ? 'Z' : ''));
301+
} else return new Date(stringValue);
302+
}
293303

294304
const numberToConvert = options.delimiter
295305
? stringValue.replace(options.delimiter, '.')
@@ -349,21 +359,21 @@ function _stringProxy<T extends Record<string, unknown>, Path extends FormPaths<
349359
case 'date':
350360
return date.toISOString().slice(0, 10);
351361
case 'datetime':
352-
return date.toISOString().slice(0, 16);
362+
return date.toISOString().slice(0, options.step % 60 ? 19 : 16);
353363
case 'time':
354-
return date.toISOString().slice(11, 16);
364+
return date.toISOString().slice(11, options.step % 60 ? 19 : 16);
355365
case 'date-utc':
356366
return UTCDate(date);
357367
case 'datetime-utc':
358-
return UTCDate(date) + 'T' + UTCTime(date);
368+
return UTCDate(date) + 'T' + UTCTime(date, options.step);
359369
case 'time-utc':
360-
return UTCTime(date);
370+
return UTCTime(date, options.step);
361371
case 'date-local':
362372
return localDate(date);
363373
case 'datetime-local':
364-
return localDate(date) + 'T' + localTime(date);
374+
return localDate(date) + 'T' + localTime(date, options.step);
365375
case 'time-local':
366-
return localTime(date);
376+
return localTime(date, options.step);
367377
}
368378
} else {
369379
// boolean
@@ -655,9 +665,12 @@ function localDate(date: Date) {
655665
);
656666
}
657667

658-
function localTime(date: Date) {
668+
function localTime(date: Date, step: number) {
659669
return (
660-
String(date.getHours()).padStart(2, '0') + ':' + String(date.getMinutes()).padStart(2, '0')
670+
String(date.getHours()).padStart(2, '0') +
671+
':' +
672+
String(date.getMinutes()).padStart(2, '0') +
673+
(step % 60 ? ':' + String(date.getSeconds()).padStart(2, '0') : '')
661674
);
662675
}
663676

@@ -671,11 +684,12 @@ function UTCDate(date: Date) {
671684
);
672685
}
673686

674-
function UTCTime(date: Date) {
687+
function UTCTime(date: Date, step: number) {
675688
return (
676689
String(date.getUTCHours()).padStart(2, '0') +
677690
':' +
678-
String(date.getUTCMinutes()).padStart(2, '0')
691+
String(date.getUTCMinutes()).padStart(2, '0') +
692+
(step % 60 ? ':' + String(date.getUTCSeconds()).padStart(2, '0') : '')
679693
);
680694
}
681695

src/routes/(v2)/v2/Navigation.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@
7676
'transport',
7777
'bigint',
7878
'issue-455',
79-
'vine'
79+
'vine',
80+
'timeproxy'
8081
].sort();
8182
</script>
8283

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { zod } from '$lib/adapters/zod.js';
2+
import { message, superValidate } from '$lib/server/index.js';
3+
import { schema } from './schema.js';
4+
import { fail } from '@sveltejs/kit';
5+
6+
export const load = async () => {
7+
const form = await superValidate(zod(schema));
8+
return { form };
9+
};
10+
11+
export const actions = {
12+
default: async ({ request }) => {
13+
const formData = await request.formData();
14+
console.log(formData);
15+
16+
const form = await superValidate(formData, zod(schema));
17+
console.log(form);
18+
19+
if (!form.valid) return fail(400, { form });
20+
21+
return message(form, 'Posted OK!');
22+
}
23+
};
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<script lang="ts">
2+
import { dateProxy, superForm } from '$lib/client/index.js';
3+
import SuperDebug from '$lib/client/SuperDebug.svelte';
4+
//import { zod } from '$lib/adapters/zod.js'
5+
//import { schema } from './schema.js';
6+
7+
export let data;
8+
9+
const { form, errors, tainted, message, enhance } = superForm(data.form, {
10+
taintedMessage: false
11+
//dataType: 'json',
12+
//validators: zod(schema)
13+
});
14+
const time = dateProxy(form, 'time', { format: 'time-utc', step: 1 });
15+
const datetime = dateProxy(form, 'datetime', { format: 'datetime-local', step: 1 });
16+
</script>
17+
18+
<SuperDebug data={{ $form, $errors, $tainted }} />
19+
20+
{#if $message}<h4>{$message}</h4>{/if}
21+
22+
<form method="POST" use:enhance>
23+
<label>
24+
Time: <input
25+
name="time"
26+
type="time"
27+
step="1"
28+
bind:value={$time}
29+
aria-invalid={$errors.time ? 'true' : undefined}
30+
/>
31+
Date and time:
32+
<input
33+
name="datetime"
34+
type="datetime-local"
35+
step="1"
36+
bind:value={$datetime}
37+
aria-invalid={$errors.time ? 'true' : undefined}
38+
/>
39+
{#if $errors.time}<span class="invalid">{$errors.time}</span>{/if}
40+
</label>
41+
<div>
42+
<button>Submit</button>
43+
</div>
44+
</form>
45+
46+
<style lang="scss">
47+
form {
48+
margin: 2rem 0;
49+
50+
input {
51+
background-color: #dedede;
52+
}
53+
54+
.invalid {
55+
color: crimson;
56+
}
57+
}
58+
</style>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { z } from 'zod';
2+
3+
export const schema = z.object({
4+
time: z.date(),
5+
datetime: z.date()
6+
});

0 commit comments

Comments
 (0)