Shyiko Skedule Save

A human-friendly alternative to cron. Designed after GAE's schedule for Kotlin and/or Java 8+.

Project README


Build Status Maven Central ktlint

A human-friendly alternative to cron.
Designed after GAE's schedule for Kotlin and/or Java 8+.


  • TZ support;
  • fluent / immutable / java.time.*-based API;
  • zero dependencies.


  <!-- omit classifier below if you plan to use this library in koltin -->


// creating schedule from a string
Schedule.parse("every monday 09:00");

// programmatic construction, 0)).every(DayOfWeek.MONDAY).toString().equals("every monday 09:00");

ZonedDateTime now = ZonedDateTime.parse("2007-12-03T10:15:30+02:00[Europe/Kiev]");
ZonedDateTime nxt = ZonedDateTime.parse("2007-12-10T09:00:00+02:00[Europe/Kiev]");

// determining "next" time
Schedule.parse("every monday 09:00").next(now).equals(nxt);

// iterating over (infinite) schedule
Schedule.parse("every monday 09:00").iterate(now)/*: Iterator<ZonedDateTime> */.next().equals(nxt);


Schedule format is described in GAE cron.xml reference.
Here are some examples (taken from the official GAE documentation):

every 12 hours
every 5 minutes from 10:00 to 14:00
every day 00:00
every monday 09:00
2nd,third mon,wed,thu of march 17:00
1st monday of sep,oct,nov 17:00
1 of jan,april,july,oct 00:00


  • hour can be used in place of 1 hours (same goes for 1 minutes)
    (e.g. every hour, every minute from 10:00 to 14:00) (since 0.3.0)
  • - can be used to join consequent days & months (e.g. every mon-fri 09:00, 1-7 of jun-aug 00:00) (since 0.3.0)

(example) Scheduling using ScheduledThreadPoolExecutor

import com.github.shyiko.skedule.Schedule;

import java.time.LocalTime;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
ZonedDateTime now =;
    () -> {
        System.out.println("TASK 'every 5 minutes from 12:00 to 12:30' EXECUTED");
        // re-schedule if needed
    Schedule.from(LocalTime.NOON, LocalTime.of(12, 30)).every(5, ChronoUnit.MINUTES)
        .next(now).toEpochSecond() - now.toEpochSecond(),
    () -> {
        System.out.println("TASK 'every day 12:00' EXECUTED");
        // re-schedule if needed
        .next(now).toEpochSecond() - now.toEpochSecond(),

NOTE #1: Be careful with java.util.TimerTask::cancel() (if you choose to go with java.util.Timer).

NOTE #2: If you are thinking of using java.util.concurrent.DelayQueue - keep in mind that remove() operation is O(n).

NOTE #3: If you have a huge number of scheduled tasks >= 10th of thousands you might want to consider switching to Hierarchical Wheel Timer(s).


git clone && cd skedule
./mvnw # shows how to build, test, etc. project

All code, unless specified otherwise, is licensed under the MIT license.
Copyright (c) 2017 Stanley Shyiko.

Open Source Agenda is not affiliated with "Shyiko Skedule" Project. README Source: shyiko/skedule
Open Issues
Last Commit
2 years ago

Open Source Agenda Badge

Open Source Agenda Rating