Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/data/scheduler/recurring-events/recurring-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ The RRULE string is composed of semicolon-separated `KEY=VALUE` pairs.
The two fundamental properties are:

- `FREQ`: the base frequency of the rule: `DAILY`, `WEEKLY`, `MONTHLY`, or `YEARLY`.
- `INTERVAL` _(optional, defaults to `1`)_: at which intervals the recurrence repeats.
- `INTERVAL` _(optional, defaults to `1`)_: at which intervals the recurrence repeats, as a positive integer.
For example, within a `DAILY` rule, a value of `8` means every eight days.

### Daily frequency
Expand Down Expand Up @@ -83,7 +83,7 @@ rrule: 'FREQ=WEEKLY;INTERVAL=2;BYDAY=MO,WE,FR';

Use either the `BYMONTHDAY` or the `BYDAY` property (both can't be defined together):

- Use the `BYMONTHDAY` property with a single day number to define the day of the month on which the event should be applied:
- Use the `BYMONTHDAY` property with a single day number, from 1 to 31, to define the day of the month on which the event should be applied:

```ts
// Every month on the 15th
Expand Down
5 changes: 5 additions & 0 deletions docs/data/scheduler/timezone/timezone.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const event = {
```

This event always happens at 09:00 in New York, regardless of DST changes.
A local time that a DST transition skips or repeats follows the same rules as the [occurrences of recurring events](#recurring-events-and-timezones).

{{"demo": "TimezoneDatasetWallTime.js", "bg": "inline", "defaultCodeOpen": false}}

Expand Down Expand Up @@ -131,6 +132,10 @@ to happen at 09:00 local time in Europe/Paris.
The Scheduler uses the event's `timezone` to interpret and expand
the recurrence pattern correctly across DST boundaries.

When a DST transition skips the local time of an occurrence, the occurrence moves forward by the length of the gap: a daily event at 02:30 in `Europe/Paris` happens at 03:30 on the day clocks spring forward.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rita-codes not sure how you want to structure this doc page
I feel like it's listing a lot of things that people won't ready 😆

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, the recurring section has grown too much. I'd move the DST rules to their own short section (they apply to wall-time events too, so the cross-link goes away), keep only the model in the recurring section, and cut the dialog part to one sentence. I can push it on this PR or do it in a follow-up after it lands, whatever you prefer.

When a transition repeats the local time, the occurrence happens the first time the clock shows it.
Both rules follow the [RFC 5545](https://datatracker.ietf.org/doc/html/rfc5545#section-3.3.5) specification.

The event dialog reads and writes the recurrence rule in the event's `timezone` too: the weekday and day of month it offers, and the "Until" day, are the ones of the event in that timezone, which can differ from the day the occurrence is displayed on.
When the event's timezone differs from the `displayTimezone`, the Recurrence tab shows a "Timezone: …" note under the recurrence selector and the read-only details append the timezone name to the recurrence label.
An event created from the UI has no `timezone` field, so the note names the system timezone (the `default` one) when the calendar displays another.
Expand Down
27 changes: 26 additions & 1 deletion docs/public/static/error-codes.json
Original file line number Diff line number Diff line change
Expand Up @@ -303,5 +303,30 @@
"303": "MUI X Data Grid: \"%s\" is not a valid formula function name. The formula parser can never produce a call to it, which would make the function unreachable in formulas. Function names must start with a letter or underscore and contain only letters, digits, and underscores.",
"304": "MUI X Data Grid: A row update with `_action: 'replace'` was provided without a `row` property.\nWithout it, the Data Grid does not know which object to store for that row.\nProvide the replacement object in the `row` property, for example `updateRows([{ _action: 'replace', row }])`.\nFor more detail, see https://mui.com/x/react-data-grid/row-updates/.",
"305": "MUI X Charts: The Content Security Policy blocked the styles copied to the export document.\nThe chart cannot be exported because the export process needs to read those styles.\nSet the `nonce` export option to the nonce used by your Content Security Policy, or set the `copyStyles` export option to `false` to export the chart without the page styles.\nA policy that allows styles by hash instead of by nonce always blocks them, because the export rebuilds the styles from the page rules and their hashes no longer match, so `copyStyles` is the only option there.\nSee https://mui.com/x/react-charts/content-security-policy/ for more details.",
"306": "MUI X Charts: Failed to render the chart as an image.\nThe chart is drawn through an image with a `data:` or `blob:` URL, so a Content Security Policy needs `img-src 'self' data: blob:`.\nSee https://mui.com/x/react-charts/content-security-policy/ for more details."
"306": "MUI X Charts: Failed to render the chart as an image.\nThe chart is drawn through an image with a `data:` or `blob:` URL, so a Content Security Policy needs `img-src 'self' data: blob:`.\nSee https://mui.com/x/react-charts/content-security-policy/ for more details.",
"307": "Base UI Plus: `BaseTemporal.PlainDate.prototype.add()` received %s, which isn't a duration. `add()` can't read years, months, weeks or days from it. Pass an object such as `{ months: 1, days: 2 }`. Duration strings such as `\"P1M\"` are not supported.",
"308": "Base UI Plus: `BaseTemporal.PlainDate.prototype.add()` received %s as the %s of a duration, which isn't an integer. A duration moves a date by whole units. Pass integers, such as `{ months: 1 }`.",
"309": "Base UI Plus: `BaseTemporal.PlainDate.prototype.add()` received a duration without years, months, weeks or days. `add()` can't tell how far to move the date. Pass at least one of these units, such as `{ days: 1 }`.",
"310": "Base UI Plus: `BaseTemporal.PlainDate.prototype.add()` received a duration with time units. A date has no time, and `add()` doesn't turn time units into days. Pass whole days instead, such as `{ days: 2 }` for 48 hours.",
"311": "Base UI Plus: `BaseTemporal.PlainDate.prototype.add()` received a duration with positive and negative units. A duration moves a date in a single direction. Pass units with the same sign, or call `add()` once per direction.",
"312": "Base UI Plus: `BaseTemporal.PlainDate.prototype.add()` moved a date of the month %s to the year %s, which doesn't have this month. The `overflow: 'reject'` option forbids moving the date to another month. Pass `overflow: 'constrain'` to use the month that replaces it.",
"313": "Base UI Plus: `BaseTemporal.PlainDate.prototype.add()` moved the day %s to a month of %s days. The `overflow: 'reject'` option forbids moving the date to the last day of the month. Pass `overflow: 'constrain'` to use the last day of the month.",
"314": "Base UI Plus: `BaseTemporal.%s` received %s, which isn't an object of date fields. `with()` replaces the date fields of an object, and keeps the calendar of the date, so it rejects temporal values and objects with a calendar or a time zone. Pass the fields to replace, such as `{ day: 1 }`, and call `withCalendar()` to change the calendar.",
"315": "Base UI Plus: `BaseTemporal.%s` received no date field the calendar of the date reads. `with()` can't tell which fields to replace. Pass at least one of `year`, `month`, `monthCode` and `day`, or `era` and `eraYear` outside the ISO calendar.",
"316": "Base UI Plus: A calendar received %s where it expects a `PlainDate`. The calendar reads the year, the month and the day of each date, so it can't use this one. Create dates with `BaseTemporal.PlainDate.from()`. A Server Component sends a `PlainDate` to the client as its string: pass that string to `from()` in a Client Component.",
"317": "Base UI Plus: `BaseTemporal.PlainDate.from()` received %s, which isn't an existing date in the `YYYY-MM-DD` format. Other ISO 8601 forms, such as times, offsets, time zone annotations or 6-digit years, are not supported. Pass a date such as `'2024-05-24'`, optionally followed by a calendar annotation such as `'[u-ca=hebrew]'`.",
"318": "Base UI Plus: `BaseTemporal.PlainDate.from()` received %s, which isn't a date. `from()` can't read a year, a month and a day from it. Pass a `PlainDate`, an object such as `{ year: 2024, month: 5, day: 24 }`, or a string such as `'2024-05-24'`.",
"319": "Base UI Plus: `BaseTemporal.%s` received date fields that %s. The fields don't name a single date of the calendar. Pass a year (or an era and a year of era), a month (or a month code) and a day that exist in the calendar.",
"320": "Base UI Plus: `BaseTemporal.%s` received an object without %s. A date can't be built without its year, month and day. Pass an object such as `{ year: 2024, month: 5, day: 24 }`, with an era and a year of era together in place of the year if needed.",
"321": "Base UI Plus: `PlainDate` received the year %s, the month %s and the day %s, which don't name a supported date. The year must be from 0 to 9999, the month from 1 to 12, and the day must exist in the month. Pass a valid date, or create it with `BaseTemporal.PlainDate.from()` and an object to move a month or a day above its range to the closest valid value.",
"322": "Base UI Plus: A temporal value received %s as its calendar, which isn't a string. Calendars are identified by their name. Pass a calendar identifier such as `'iso8601'`, `'gregory'` or `'hebrew'`.",
"323": "Base UI Plus: The \"%s\" calendar isn't supported. Base UI Plus has no arithmetic for it, so it cannot create or display its dates. Use `iso8601`, `gregory`, or one of the calendars listed in the documentation.",
"324": "Base UI Plus: The \"%s\" calendar isn't registered. Only the ISO and Gregorian calendars are built in, so other calendars stay out of the bundles that don't use them. Pass `%sCalendar` to `registerCalendar()`, both from `@base-ui/plus/calendar-systems`, before creating or displaying its dates.",
"325": "Base UI Plus: `registerCalendar()` received %s, which isn't a calendar of `@base-ui/plus/calendar-systems`. Base UI Plus only registers the calendars it implements. Pass a calendar such as `hebrewCalendar` from `'@base-ui/plus/calendar-systems'`.",
"326": "Base UI Plus: `registerCalendar()` received a second implementation of the \"%s\" calendar. Two implementations could give different dates for the same values, so the first registration stays. Make sure a single copy of `@base-ui/plus` is installed, and register each calendar once.",
"327": "Base UI Plus: A date of the \"%s\" calendar is outside the days it supports, from the ISO date %s-%s-%s to %s-%s-%s. Outside these days, `Intl.DateTimeFormat` doesn't label dates as Base UI Plus computes them, or the ISO year is outside 0 to 9999. Use a date inside the range.",
"328": "Base UI Plus: A temporal value received %s as the %s, which isn't a finite number. A temporal value cannot represent a non-finite field. Pass finite numbers for its date and time fields.",
"329": "Base UI Plus: The options of `BaseTemporal.%s` are %s, which isn't an object. The method can't read the `overflow` option from them. Pass an object such as `{ overflow: 'reject' }`, or no options.",
"330": "Base UI Plus: The `overflow` option of `BaseTemporal.%s` is %s, which isn't supported. The method can't tell whether to adjust or reject a field above its range. Pass `'constrain'` or `'reject'`.",
"331": "Base UI Plus: A `%s` was converted to a primitive value, for example by `<`, `>` or `+`. Comparing or adding temporal values this way gives meaningless results, so it isn't allowed. Use the static `compare()` method or `equals()` to compare them, and `toString()` to get them as a string."
}
8 changes: 8 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,14 @@ export default defineConfig(
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
},
},
{
// A copy of BaseTemporal from Base UI Plus, which keeps its code style.
files: [`packages/x-scheduler-internals/src/internals/utils/base-temporal/*${EXTENSION_TS}`],
rules: {
'import/consistent-type-specifier-style': 'off',
'jsdoc/no-bad-blocks': 'off',
},
},
{
files: [`**/*${EXTENSION_TEST_FILE}`, `test/**/*${EXTENSION_TS}`],
rules: {
Expand Down
Loading
Loading