Coder Social home page Coder Social logo

skedule's Introduction

skedule

Build Status Maven Central ktlint

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

Features:

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

Usage

<dependency>
  <groupId>com.github.shyiko.skedule</groupId>
  <artifactId>skedule</artifactId>
  <version>0.4.0</version>
  <!-- omit classifier below if you plan to use this library in koltin -->
  <classifier>kalvanized</classifier>
</dependency>

(java)

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

// programmatic construction
Schedule.at(LocalTime.of(9, 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);

Format

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

Additionally:

  • 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);
executor.setRemoveOnCancelPolicy(true);
ZonedDateTime now = ZonedDateTime.now();
executor.schedule(
    () -> {
        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(),
    TimeUnit.SECONDS
);
executor.schedule(
    () -> {
        System.out.println("TASK 'every day 12:00' EXECUTED");
        // re-schedule if needed
    },
    Schedule.at(LocalTime.NOON).everyDay()
        .next(now).toEpochSecond() - now.toEpochSecond(),
    TimeUnit.SECONDS
);

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).

Development

git clone https://github.com/shyiko/skedule && cd skedule
./mvnw # shows how to build, test, etc. project

Legal

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

skedule's People

Contributors

shyiko avatar sjurba avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

skedule's Issues

Add support for seconds and milliseconds

If this library supported scheduling down to millisecond it would make a really great and universal solution for scheduling processes.

Ex:

  • "every second"
  • "every 15 seconds"
  • "every 250 millis from 10:00 to 11:00"

nextOrSame documentation/example

I am just trying to use the ScheduleIterator and can not figure out what the difference is between next() and nextOrSame(), it would be nice if the readme would contain an example/documentation, or there was documentation about its intents in the code.

Thanks for this great library btw, it really is turning out to be useful.

Recurring execution of Schedule's

I think a method like this would be quite helpful:

fun Schedule.schedule(executor: ThreadPoolExecutor, code: () -> Unit) {
    val now = ZonedDateTime.now()
    val next = this.next(
        now
            .minusSeconds(now.second.toLong())
            .minusNanos(now.nano.toLong())
    )
    val delay = next.toEpochSecond() - now.toEpochSecond()
    executor.schedule(
        {
            this.schedule(code)
            code()
        },
        delay,
        TimeUnit.SECONDS
    )
}

because the example in the README.md is not recurring

Doesn't work with x-st of month

val schedule = parse("first monday of month 09:00");
Fails:

Exception in thread "main" com.github.shyiko.skedule.InvalidScheduleException: "month" isn't a valid month
	at com.github.shyiko.skedule.internal.ScheduleImpl.parseMonth(ScheduleImpl.kt:113)
	at com.github.shyiko.skedule.internal.ScheduleImpl.parse(ScheduleImpl.kt:173)
	at com.github.shyiko.skedule.Schedule.parse(Schedule.java:36)
	at no.entro.subscriptions.scheduling.SchedulerKt.main(Scheduler.kt:8)
	at no.entro.subscriptions.scheduling.SchedulerKt.main(Scheduler.kt)

scheduleiterator looping over the same value over and over again

I have a schedule setup as follows:

val now = ZonedDateTime.now(ZoneId.of("UTC"))
val scheduleIterator = Schedule.at(now.plusNanos(1000).toLocalTime()).everyDay().iterate(now)
println(scheduleIterator.next())
println(scheduleIterator.next())
println(scheduleIterator.next())
...

and all calls to next print exactly the same ZonedDateTime. Is that an issue with the library or am I using this somehow wrong?

Iterable starting from "same"

It would be nice if it was possible to call a variation of the iterate method that starts at the "same" instant as the timestamp.

Since I am using Kotlin, and want a Sequence rather than an Iterator I am working around this with the following extensions:

/**
 * Similar to `asSequence` on [ScheduleIterator] but calls `nextOrSame` instead of `next` to obtain the
 * first element.
 */
fun <T> Schedule.ScheduleIterator<T>.asSequenceStartingFromNextOrSame(): Sequence<T> = generateSequence({ nextOrSame() }) {
  next()
}

fun Schedule.asSequence(timestamp: ZonedDateTime, startingFromSame: Boolean = false): Sequence<ZonedDateTime> {
  val scheduleIterator = iterate(timestamp)
  return if(startingFromSame) scheduleIterator.asSequenceStartingFromNextOrSame() else scheduleIterator.asSequence()
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.