|
1 | 1 | # Date type
|
2 | 2 |
|
3 |
| -The date schema type validates the field's value to be a string formatted as a date. The output get's converted to an instance of [Luxon DateTime](https://moment.github.io/luxon/api-docs/index.html#datetime) class. |
| 3 | +Ensure the field's value is a string formatted as a date or datetime per the expected formats. The return value is an instance of the [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) class. |
4 | 4 |
|
5 |
| -To use the `vine.date` method, you must install [luxon](https://moment.github.io/luxon/#/install) as your project dependency. |
| 5 | +```ts |
| 6 | +import vine from '@vinejs/vine' |
6 | 7 |
|
7 |
| -```sh |
8 |
| -npm i luxon |
| 8 | +const schema = vine.object({ |
| 9 | + published_at: vine.date() |
| 10 | +}) |
9 | 11 | ```
|
10 | 12 |
|
11 |
| -Once installed, you may use the date schema type as follows. |
| 13 | +By default, the input value should be formatted as a `YYYY-MM-DD` or `YYYY-MM-DD HH:mm:ss` string. However, you may define custom formats as well. In the following example, we expect the input string to be valid per any of the mentioned formats. |
| 14 | + |
| 15 | +:::note |
| 16 | + |
| 17 | +You must check the Day.js documentation to [view the available formatting tokens](https://day.js.org/docs/en/parse/string-format#list-of-all-available-parsing-tokens). |
| 18 | + |
| 19 | +::: |
12 | 20 |
|
13 | 21 | ```ts
|
14 | 22 | import vine from '@vinejs/vine'
|
15 | 23 |
|
16 | 24 | const schema = vine.object({
|
17 |
| - dob: vine.date(), |
| 25 | + published_at: vine.date({ |
| 26 | + formats: ['YYYY/DD/MM', 'x'] |
| 27 | + }) |
18 | 28 | })
|
19 |
| - |
20 |
| -const data = { |
21 |
| - dob: '1990-05-23' |
22 |
| -} |
23 |
| - |
24 |
| -const output = await vine.validate({ schema, data }) |
25 |
| - |
26 |
| -output.dob // DateTime |
27 | 29 | ```
|
28 | 30 |
|
29 |
| -## Defining format and zone |
| 31 | +You may mark the field as `optional` or `nullable` using the following modifiers. |
30 | 32 |
|
31 |
| -The date values are validated against the `ISO` format by default. However, using the `format` option, you may define a custom format. |
| 33 | +See also: [Working with `undefined` and `null` values](../guides/schema_101.md#nullable-and-optional-modifiers) |
32 | 34 |
|
33 | 35 | ```ts
|
34 |
| -vine.date({ format: 'iso' }) |
35 |
| -vine.date({ format: 'sql' }) |
36 |
| -vine.date({ format: 'yyyy-MM-dd HH:mm:ss' }) |
| 36 | +{ |
| 37 | + published_at: vine.date().nullable() |
| 38 | +} |
37 | 39 | ```
|
38 | 40 |
|
39 |
| -You may use the following shorthand keywords or use any available [Luxon DateTime tokens](https://moment.github.io/luxon/#/parsing?id=table-of-tokens) to define the format. |
| 41 | +```ts |
| 42 | +{ |
| 43 | + published_at: vine.date().optional() |
| 44 | +} |
| 45 | +``` |
40 | 46 |
|
41 |
| -- `iso` |
42 |
| -- `sql` |
43 |
| -- `rfc2822` |
44 |
| -- `http` |
45 | 47 |
|
46 |
| -Post validation, the DateTime instance is created in the local timezone of your server. However, you may [define an explicit zone](https://moment.github.io/luxon/#/zones?id=creating-datetimes-in-a-zone) using the `zone` property. |
| 48 | +## Defining error message |
| 49 | +You may define custom error messages for the following date-based rules. |
47 | 50 |
|
48 | 51 | ```ts
|
49 |
| -vine.date({ |
50 |
| - zone: 'utc' |
51 |
| -}) |
| 52 | +const messages = { |
| 53 | + 'date': 'The {{ field }} field must be a datetime value', |
| 54 | + |
| 55 | + 'date.equals': 'The {{ field }} field must be a date equal to {{ expectedValue }}', |
| 56 | + 'date.after': 'The {{ field }} field must be a date after {{ expectedValue }}', |
| 57 | + 'date.before': 'The {{ field }} field must be a date before {{ expectedValue }}', |
| 58 | + 'date.afterOrEqual': 'The {{ field }} field must be a date after or equal to {{ expectedValue }}', |
| 59 | + 'date.beforeOrEqual': 'The {{ field }} field must be a date before or equal to {{ expectedValue }}', |
| 60 | + |
| 61 | + 'date.sameAs': 'The {{ field }} field and {{ otherField }} field must be the same', |
| 62 | + 'date.notSameAs': 'The {{ field }} field and {{ otherField }} field must be different', |
| 63 | + 'date.afterField': 'The {{ field }} field must be a date after {{ otherField }}', |
| 64 | +} |
| 65 | + |
| 66 | +vine.messagesProvider = new SimpleMessagesProvider(messages) |
52 | 67 | ```
|
53 | 68 |
|
54 |
| -## Validations |
| 69 | +## Comparing dates |
| 70 | +You may use one of the following validation methods to compare the user input against a specific datetime value. |
| 71 | + |
| 72 | +- `equals`: Ensure the input datetime value is the same as the expected datetime value. |
55 | 73 |
|
56 |
| -Following is the list of validation rules you may apply on a date. |
| 74 | +- `after`: Ensure the input datetime value is after the expected datetime value. |
57 | 75 |
|
58 |
| -### equals |
59 |
| -Ensure the value of date is same as the pre-defined value. The expected value must be an instance of the Luxon DateTime class. |
| 76 | +- `afterOrEqual`: Same as the `after` method, but performs a greater than and equal to comparison. |
| 77 | + |
| 78 | +- `before`: Ensure the input datetime value is before the expected datetime value. |
| 79 | + |
| 80 | +- `beforeOrEqual`: Same as the `before` method, but performs a less than and equal to comparison. |
60 | 81 |
|
61 | 82 | ```ts
|
| 83 | +// title: Example of equals |
62 | 84 | const schema = vine.object({
|
63 | 85 | enrollment_date: vine
|
64 | 86 | .date()
|
65 |
| - .equals(DateTime.fromISO('2023-05-25')) |
| 87 | + .equals('2024-01-28') |
66 | 88 | })
|
67 | 89 | ```
|
68 | 90 |
|
69 |
| -### notEquals |
70 |
| -Ensure the value of date is not same as the pre-defined value. The expected value must be an instance of the Luxon DateTime class. |
71 |
| - |
72 | 91 | ```ts
|
| 92 | +// title: Example of after |
73 | 93 | const schema = vine.object({
|
74 |
| - enrollment_date: vine |
| 94 | + checkin_date: vine |
75 | 95 | .date()
|
76 |
| - .notEquals(DateTime.fromISO('2023-05-25')) |
| 96 | + .after('today') |
77 | 97 | })
|
78 |
| -``` |
79 |
| - |
80 |
| -### sameAs |
81 | 98 |
|
82 |
| -### notSameAs |
83 |
| - |
84 |
| -### after / afterOrEqual |
| 99 | +const schema = vine.object({ |
| 100 | + checkin_date: vine |
| 101 | + .date() |
| 102 | + .after('2024-01-01') |
| 103 | +}) |
| 104 | +``` |
85 | 105 |
|
86 |
| -Ensure the date is after a given interval. The `after` and `afterOrEqual` methods accepts the interval as the `first` argument and the unit as the `second` argument. |
| 106 | +When using dynamic or computed values, you must use a callback function. Otherwise, the initial value will be cached forever with a [precompiled schema](../guides/getting_started.md#pre-compiling-schema). |
87 | 107 |
|
88 | 108 | ```ts
|
| 109 | +// title: Lazily compute the expected value |
89 | 110 | const schema = vine.object({
|
90 |
| - checkin_date: vine |
| 111 | + enrollment_date: vine |
91 | 112 | .date()
|
92 |
| - .after(2, 'days') |
| 113 | + // highlight-start |
| 114 | + .afterOrEqual((field) => { |
| 115 | + return dayjs().add(2, 'day').format('YYYY-MM-DD') |
| 116 | + }) |
| 117 | + // highlight-end |
93 | 118 | })
|
94 | 119 | ```
|
95 | 120 |
|
96 |
| -Following is the list of available units. |
| 121 | +### How is the comparison performed? |
| 122 | +Validation rules use the `compare` unit to compare the two dates. By default, the compare unit is set to `day`, which means the validation will compare the `day`, `month`, and the `year` values. |
| 123 | + |
| 124 | +Similarly, if you set the compare unit to `minutes`, the validation will compare `minutes`, `hours`, `day`, `month` and the `year`. |
| 125 | + |
| 126 | +:::tip |
| 127 | + |
| 128 | +Under the hood, the comparison is performed using the [Days.js query methods](https://day.js.org/docs/en/query/is-before). |
| 129 | + |
| 130 | +::: |
97 | 131 |
|
98 | 132 | ```ts
|
99 |
| -vine.date().after(2, 'days') |
100 |
| -vine.date().after(1, 'month') |
101 |
| -vine.date().after(3, 'years') |
102 |
| -vine.date().after(30, 'minutes') |
103 |
| -vine.date().after(2, 'quarters') |
| 133 | +vine |
| 134 | + .date() |
| 135 | + .equals('2024-01-28', { |
| 136 | + compare: 'month', // compares month and the year |
| 137 | + }) |
104 | 138 | ```
|
105 | 139 |
|
106 |
| -For advanced use cases, you may pass an instance of the Luxon DateTime directly. |
| 140 | +### Using a custom format |
| 141 | +Validation rules assume the expected datetime format to be an ISO string. However, you may use the `format` option to specify a custom format. |
107 | 142 |
|
108 | 143 | ```ts
|
109 | 144 | vine
|
110 | 145 | .date()
|
111 |
| - .after(DateTime.utc(), 'days') |
| 146 | + .equals('2024/28/01', { |
| 147 | + format: 'YYYY/DD/MM', |
| 148 | + }) |
112 | 149 | ```
|
113 | 150 |
|
114 |
| -### afterField / afterOrSameAsField |
| 151 | +## Comparing against other fields |
| 152 | +Alongside performing [comparison against a fixed datetime value](#comparing-dates), you may also use the following validation methods to compare the input value against the value of another field. |
115 | 153 |
|
116 |
| -The `afterField` and `afterOrSameAsField` methods enforce the date to be after the date value of the other field. |
| 154 | +- `sameAs`: Ensure the input datetime value is the same as the other field's value. |
117 | 155 |
|
118 |
| -The `afterField` validation is skipped when the other field's value is not a valid date. |
| 156 | +- `notSameAs`: Ensure the input datetime value is not the same as the other field's value. |
119 | 157 |
|
120 |
| -```ts |
121 |
| -const schema = vine.object({ |
122 |
| - checkin_date: vine.date().inFuture({ unit: 'days' }), |
123 |
| - checkout_date: vine |
124 |
| - .date() |
125 |
| - .afterField('checkin_date'), |
126 |
| -}) |
127 |
| -``` |
| 158 | +- `afterField`: Ensure the input datetime value is after the other field's value. |
| 159 | + |
| 160 | +- `afterOrSameAs`: Same as the `afterField` rule, but performs a greater than and equal to comparison. |
128 | 161 |
|
129 |
| -By default, the diff between two dates is calculated in minutes. However, you may define a custom diff unit via the options object. |
| 162 | +- `beforeField`: Ensure the input datetime value is before the other field's value. |
| 163 | + |
| 164 | +- `beforeOrSameAs`: Same as the `beforeField` rule, but performs a less than and equal to comparison. |
130 | 165 |
|
131 | 166 | ```ts
|
| 167 | +// title: Example of sameAs |
132 | 168 | const schema = vine.object({
|
133 |
| - checkin_date: vine.date().inFuture({ unit: 'days' }), |
134 |
| - checkout_date: vine |
135 |
| - .date() |
136 |
| - .afterField('checkin_date', { unit: 'days' }), |
| 169 | + entry_date: vine.date(), |
| 170 | + exit_date: vine.date().sameAs('entry_date') |
137 | 171 | })
|
138 | 172 | ```
|
139 | 173 |
|
140 |
| - |
141 |
| -### before / beforeOrEqual |
142 |
| - |
143 |
| -Ensure the date is before a given interval. The `before` and `beforeOrEqual` methods accept the interval as the `first` argument and the unit as the `second` argument. |
144 |
| - |
145 | 174 | ```ts
|
| 175 | +// title: Example of afterField |
146 | 176 | const schema = vine.object({
|
147 |
| - dob: vine |
148 |
| - .date() |
149 |
| - .before(10, 'years') |
| 177 | + checkin_date: vine.date(), |
| 178 | + checkout_date: vine.date().afterField('checkin_date') |
150 | 179 | })
|
151 | 180 | ```
|
152 | 181 |
|
153 |
| -Following is the list of available units. |
154 |
| - |
155 |
| -```ts |
156 |
| -vine.date().before(2, 'days') |
157 |
| -vine.date().before(1, 'month') |
158 |
| -vine.date().before(3, 'years') |
159 |
| -vine.date().before(30, 'minutes') |
160 |
| -vine.date().before(2, 'quarters') |
161 |
| -``` |
| 182 | +You may specify the comparison unit and the format of the other field using the options object. |
162 | 183 |
|
163 |
| -For advanced use cases, you may pass an instance of the Luxon DateTime directly. |
| 184 | +See also: [How is the comparison performed?](#how-is-the-comparison-performed) |
164 | 185 |
|
165 | 186 | ```ts
|
166 |
| -vine |
167 |
| - .date() |
168 |
| - .before(DateTime.utc().minus({ days: 1 })) |
| 187 | +const schema = vine.object({ |
| 188 | + checkin_date: vine.date({ |
| 189 | + formats: ['YYYY/MM/DD'] |
| 190 | + }), |
| 191 | + checkout_date: vine.date().afterField('checkin_date', { |
| 192 | + compare: 'day', |
| 193 | + format: ['YYYY/MM/DD'] |
| 194 | + }) |
| 195 | +}) |
169 | 196 | ```
|
170 | 197 |
|
171 |
| -### beforeField / beforeOrSameAsField |
| 198 | +## Other validation rules |
| 199 | +Following is the list of other (non-comparison) validation rules. |
172 | 200 |
|
173 |
| -The `beforeField` and `beforeOrSameAsField` methods enforce the date to be before the date value of the other field. |
174 |
| - |
175 |
| -The `beforeField` validation is skipped when the other field's value is not a valid date. |
| 201 | +### weekend |
| 202 | +Ensure the date is a weekend. |
176 | 203 |
|
177 | 204 | ```ts
|
178 | 205 | const schema = vine.object({
|
179 |
| - checkin_date: vine.date(), |
180 |
| - documents_approved_at: vine |
181 |
| - .date() |
182 |
| - .beforeField('checkin_date') |
| 206 | + checkin_date: vine.date().weekend() |
183 | 207 | })
|
184 | 208 | ```
|
185 | 209 |
|
186 |
| -By default, the diff between two dates is calculated in minutes. However, you may define a custom diff unit via the options object. |
| 210 | +### weekday |
| 211 | +Ensure the date is a weekday. |
187 | 212 |
|
188 | 213 | ```ts
|
189 | 214 | const schema = vine.object({
|
190 |
| - checkin_date: vine.date(), |
191 |
| - documents_approved_at: vine |
192 |
| - .date() |
193 |
| - .beforeField('checkin_date', { unit: 'days' }) |
| 215 | + event_date: vine.date().weekday() |
194 | 216 | })
|
195 | 217 | ```
|
196 |
| - |
197 |
| -### inFuture |
198 |
| - |
199 |
| -### inPast |
200 |
| - |
201 |
| -### weekday |
202 |
| - |
203 |
| -### weekend |
|
0 commit comments