Skip to content

Commit 01cf082

Browse files
aster-voidclaude
andcommitted
config: add "inherit" timezone to use system timezone
Adds support for `timezone: inherit` in runner config to use the system's local timezone instead of specifying an explicit IANA name. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 7936a46 commit 01cf082

File tree

4 files changed

+45
-15
lines changed

4 files changed

+45
-15
lines changed

CLAUDE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ struct ScheduleConfig { cron: String }
4545
## Config Format
4646

4747
```yaml
48+
runner: # Optional: global settings
49+
timezone: Asia/Tokyo # Optional: IANA name, "inherit" (system), or omit for UTC
50+
4851
jobs:
4952
<job-id>: # Key = ID (used for directories)
5053
name: "Display Name" # Optional (defaults to job-id)

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ rollcron https://github.com/ut-code/rollcron
7070
```yaml
7171
runner: # Optional: global settings
7272
timezone: Asia/Tokyo # Timezone for cron schedules (default: UTC)
73+
# Use "inherit" to use system timezone
7374

7475
jobs:
7576
<job-id>: # Key is the job ID (used for directories)
@@ -93,7 +94,7 @@ Global settings that apply to all jobs:
9394
9495
| Field | Description |
9596
|-------|-------------|
96-
| `timezone` | Timezone for cron schedule interpretation (e.g., `Asia/Tokyo`, `America/New_York`) |
97+
| `timezone` | Timezone for cron schedule interpretation. Use IANA names (e.g., `Asia/Tokyo`, `America/New_York`), `inherit` (system timezone), or omit for UTC |
9798

9899
### Concurrency
99100

src/config.rs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,17 @@ use std::collections::HashMap;
66
use std::str::FromStr;
77
use std::time::Duration;
88

9+
#[derive(Debug, Clone, Default, PartialEq)]
10+
pub enum TimezoneConfig {
11+
#[default]
12+
Utc,
13+
Inherit,
14+
Named(Tz),
15+
}
16+
917
#[derive(Debug, Clone, Default)]
1018
pub struct RunnerConfig {
11-
pub timezone: Option<Tz>,
19+
pub timezone: TimezoneConfig,
1220
}
1321

1422
#[derive(Debug, Deserialize, Default)]
@@ -93,12 +101,14 @@ pub fn parse_config(content: &str) -> Result<(RunnerConfig, Vec<Job>)> {
93101
let config: Config = serde_yaml::from_str(content)
94102
.map_err(|e| anyhow!("Failed to parse YAML: {}", e))?;
95103

96-
let timezone = config
97-
.runner
98-
.timezone
99-
.map(|s| s.parse::<Tz>())
100-
.transpose()
101-
.map_err(|e| anyhow!("Invalid timezone: {}", e))?;
104+
let timezone = match config.runner.timezone {
105+
None => TimezoneConfig::Utc,
106+
Some(s) if s == "inherit" => TimezoneConfig::Inherit,
107+
Some(s) => TimezoneConfig::Named(
108+
s.parse::<Tz>()
109+
.map_err(|e| anyhow!("Invalid timezone '{}': {}", s, e))?,
110+
),
111+
};
102112

103113
let runner = RunnerConfig { timezone };
104114

@@ -344,7 +354,7 @@ jobs:
344354
run: echo test
345355
"#;
346356
let (runner, _) = parse_config(yaml).unwrap();
347-
assert_eq!(runner.timezone, Some(chrono_tz::Asia::Tokyo));
357+
assert_eq!(runner.timezone, TimezoneConfig::Named(chrono_tz::Asia::Tokyo));
348358
}
349359

350360
#[test]
@@ -357,7 +367,22 @@ jobs:
357367
run: echo test
358368
"#;
359369
let (runner, _) = parse_config(yaml).unwrap();
360-
assert!(runner.timezone.is_none());
370+
assert_eq!(runner.timezone, TimezoneConfig::Utc);
371+
}
372+
373+
#[test]
374+
fn parse_timezone_inherit() {
375+
let yaml = r#"
376+
runner:
377+
timezone: inherit
378+
jobs:
379+
test:
380+
schedule:
381+
cron: "* * * * *"
382+
run: echo test
383+
"#;
384+
let (runner, _) = parse_config(yaml).unwrap();
385+
assert_eq!(runner.timezone, TimezoneConfig::Inherit);
361386
}
362387

363388
#[test]

src/scheduler.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use crate::config::{Concurrency, Job, RetryConfig, RunnerConfig};
1+
use crate::config::{Concurrency, Job, RetryConfig, RunnerConfig, TimezoneConfig};
22
use crate::git;
33
use anyhow::Result;
4-
use chrono::{TimeZone, Utc};
4+
use chrono::{Local, TimeZone, Utc};
55
use rand::Rng;
66
use std::collections::HashMap;
77
use std::path::PathBuf;
@@ -18,9 +18,10 @@ pub async fn run_scheduler(jobs: Vec<Job>, sot_path: PathBuf, runner: RunnerConf
1818

1919
loop {
2020
for job in &jobs {
21-
let is_due = match runner.timezone {
22-
Some(tz) => is_job_due(&job.schedule, tz),
23-
None => is_job_due(&job.schedule, Utc),
21+
let is_due = match &runner.timezone {
22+
TimezoneConfig::Utc => is_job_due(&job.schedule, Utc),
23+
TimezoneConfig::Inherit => is_job_due(&job.schedule, Local),
24+
TimezoneConfig::Named(tz) => is_job_due(&job.schedule, *tz),
2425
};
2526

2627
if is_due {

0 commit comments

Comments
 (0)