|
| 1 | +# Schedule Timezone Display Specification |
| 2 | + |
| 3 | +## Purpose |
| 4 | + |
| 5 | +Defines how the frontend displays cron-based schedule times to users. All schedules are stored and configured in UTC. The frontend annotates displayed times with the UTC label and, when the user's browser is not in UTC, appends the local timezone equivalent so users can understand when a schedule will fire in their own timezone without performing mental offset calculations. |
| 6 | + |
| 7 | +## Requirements |
| 8 | + |
| 9 | +### Requirement: UTC Label on Daily-or-Longer Schedules |
| 10 | + |
| 11 | +When displaying a human-readable cron description for a schedule that fires once per day or less frequently (daily, weekly, monthly), the system SHALL insert "UTC" immediately after the time portion in the description. |
| 12 | + |
| 13 | +#### Scenario: Daily schedule at 09:00 |
| 14 | + |
| 15 | +- GIVEN a cron expression `0 9 * * *` |
| 16 | +- WHEN the frontend renders the schedule description |
| 17 | +- THEN the description SHALL contain "09:00 UTC" or "9:00 AM UTC" |
| 18 | + |
| 19 | +#### Scenario: Weekday schedule at 14:30 |
| 20 | + |
| 21 | +- GIVEN a cron expression `30 14 * * 1-5` |
| 22 | +- WHEN the frontend renders the schedule description |
| 23 | +- THEN the description SHALL contain "14:30 UTC" or "02:30 PM UTC" |
| 24 | + |
| 25 | +#### Scenario: Monthly schedule |
| 26 | + |
| 27 | +- GIVEN a cron expression `0 12 1 * *` |
| 28 | +- WHEN the frontend renders the schedule description |
| 29 | +- THEN the description SHALL contain "UTC" after the time portion |
| 30 | + |
| 31 | +### Requirement: Local Timezone Parenthetical |
| 32 | + |
| 33 | +When the user's browser timezone differs from UTC, the system SHALL append the equivalent local time in parentheses after the UTC-labeled description. |
| 34 | + |
| 35 | +#### Scenario: User in UTC+1 viewing a daily schedule |
| 36 | + |
| 37 | +- GIVEN a cron expression `0 9 * * *` |
| 38 | +- AND the user's browser is in a UTC+1 timezone |
| 39 | +- WHEN the frontend renders the schedule description |
| 40 | +- THEN the output SHALL match the pattern `<description> UTC (<local time> <timezone>)` |
| 41 | +- AND the local time SHALL reflect the browser's offset (e.g., "10:00 AM GMT+1") |
| 42 | + |
| 43 | +#### Scenario: User in UTC viewing a daily schedule |
| 44 | + |
| 45 | +- GIVEN a cron expression `0 9 * * *` |
| 46 | +- AND the user's browser is in UTC |
| 47 | +- WHEN the frontend renders the schedule description |
| 48 | +- THEN the output SHALL contain "UTC" |
| 49 | +- AND the output SHALL NOT contain a parenthesized local time (since local equals UTC) |
| 50 | + |
| 51 | +### Requirement: Sub-Daily Schedules Omit Timezone Annotation |
| 52 | + |
| 53 | +Schedules that fire more frequently than once per day (every minute, every N minutes, hourly, every N hours) SHALL display the plain cron description without any UTC label or local timezone parenthetical. |
| 54 | + |
| 55 | +#### Scenario: Every 5 minutes |
| 56 | + |
| 57 | +- GIVEN a cron expression `*/5 * * * *` |
| 58 | +- WHEN the frontend renders the schedule description |
| 59 | +- THEN the output SHALL be the plain human-readable description (e.g., "Every 5 minutes") |
| 60 | +- AND the output SHALL NOT contain "UTC" |
| 61 | + |
| 62 | +#### Scenario: Every 2 hours |
| 63 | + |
| 64 | +- GIVEN a cron expression `0 */2 * * *` |
| 65 | +- WHEN the frontend renders the schedule description |
| 66 | +- THEN the output SHALL be the plain human-readable description |
| 67 | +- AND the output SHALL NOT contain "UTC" |
| 68 | + |
| 69 | +#### Scenario: Hourly |
| 70 | + |
| 71 | +- GIVEN a cron expression `0 * * * *` |
| 72 | +- WHEN the frontend renders the schedule description |
| 73 | +- THEN the output SHALL be the plain human-readable description |
| 74 | +- AND the output SHALL NOT contain "UTC" |
| 75 | + |
| 76 | +### Requirement: Sub-Daily Detection |
| 77 | + |
| 78 | +The system SHALL determine whether a schedule is sub-daily by comparing the interval between consecutive future run times. If the interval between the first two next runs is less than 24 hours, the schedule is sub-daily. |
| 79 | + |
| 80 | +#### Scenario: Every 12 hours classified as sub-daily |
| 81 | + |
| 82 | +- GIVEN a cron expression `0 */12 * * *` |
| 83 | +- WHEN the system evaluates whether the schedule is sub-daily |
| 84 | +- THEN it SHALL classify the schedule as sub-daily regardless of the current time of day |
| 85 | + |
| 86 | +### Requirement: Graceful Fallback |
| 87 | + |
| 88 | +The system SHALL gracefully handle invalid or unparseable cron expressions by returning the raw expression string without modification. |
| 89 | + |
| 90 | +#### Scenario: Invalid cron expression |
| 91 | + |
| 92 | +- GIVEN an invalid cron expression `not-a-cron` |
| 93 | +- WHEN the frontend renders the schedule description |
| 94 | +- THEN the output SHALL be the raw string `not-a-cron` |
| 95 | + |
| 96 | +#### Scenario: Cron expression with no recognizable time portion |
| 97 | + |
| 98 | +- GIVEN a valid cron expression whose human-readable description does not contain a recognizable time pattern |
| 99 | +- WHEN the frontend renders the schedule description |
| 100 | +- THEN the output SHALL be the plain description without UTC annotation |
| 101 | + |
| 102 | +### Requirement: Both 12-Hour and 24-Hour Format Support |
| 103 | + |
| 104 | +The system SHALL correctly identify and annotate time portions in both 12-hour format (e.g., "02:30 PM") and 24-hour format (e.g., "14:30"), depending on the user's locale settings. |
| 105 | + |
| 106 | +#### Scenario: 24-hour locale |
| 107 | + |
| 108 | +- GIVEN a cron expression `30 14 * * *` |
| 109 | +- AND the user's locale produces 24-hour time format "14:30" |
| 110 | +- WHEN the frontend renders the schedule description |
| 111 | +- THEN the output SHALL contain "14:30 UTC" |
| 112 | + |
| 113 | +#### Scenario: 12-hour locale |
| 114 | + |
| 115 | +- GIVEN a cron expression `30 14 * * *` |
| 116 | +- AND the user's locale produces 12-hour time format "02:30 PM" |
| 117 | +- WHEN the frontend renders the schedule description |
| 118 | +- THEN the output SHALL contain "02:30 PM UTC" |
0 commit comments