using CronExpressionDescriptor;
using System.Globalization;
using System.Collections.Generic;
public static void Main()
var cronExpressions = new []
"* 0-19 7-9 OCT FRI,SAT,SUN",
foreach (var cronExpression in cronExpressions)
CronExpression expression = CronExpression.Parse("* * * * *");
DateTimeOffset? next = expression.GetNextOccurrence(DateTimeOffset.Now, TimeZoneInfo.Local);
var nextLocalTime = next?.DateTime;
DateTime? newInput = DateTime.UtcNow;
for(var i = 0; i < 5; i++) {
CronExpression newExpression = CronExpression.Parse("1/5 * * * *");
newInput = newExpression.GetNextOccurrence((DateTime)newInput);
DateTime? date = DateTimeOffset.UtcNow.ToUniversalTime().UtcDateTime;
var expressions = (new string[] {"0 2 * * SAT", "0 2 1 * *"}).Select(e => CronExpression.Parse(e));
date = GetNextOccurrence(expressions, date.Value);
} while(date <= new DateTime(2024,1,1));
private static void NextOccurrences(){
DateTime date = DateTime.UtcNow;
DateTime end = DateTime.Now.AddDays(10);
CronExpression expression = CronExpression.Parse("0 8 * * *");
List<DateTime> dates = new List<DateTime>();
date = (DateTime)expression.GetNextOccurrence(date);
private static void Explain(string cron)
var cronExpression = CronExpression.Parse(cron);
var utcNow = DateTime.UtcNow;
var nextOccurrence = cronExpression.GetNextOccurrence(utcNow, TimeZoneInfo.Utc);
var expressionDescriptor = ExpressionDescriptor.GetDescription(cron);
Console.WriteLine($"cronExpression: {cronExpression}");
Console.WriteLine($"utcNow: {utcNow}");
Console.WriteLine($"nextOccurrence: {nextOccurrence}");
Console.WriteLine($"description: {expressionDescriptor}");
IsDown(utcNow, nextOccurrence);
Console.WriteLine(new string('-', 40));
private static void IsDown(DateTime utcNow, DateTime? nextOccurrence)
if (nextOccurrence.HasValue)
var secondsToNextRun = nextOccurrence.Value.Subtract(utcNow).TotalSeconds;
Console.WriteLine($"Seconds to next run: {secondsToNextRun}");
if (secondsToNextRun >= 0D && secondsToNextRun <= 60D)
Console.WriteLine($"IS DOWN");
Console.WriteLine($"IS UP");
public static DateTime? GetNextOccurrence(IEnumerable<CronExpression> expressions, DateTime start)
DateTime? nextOccurrence = DateTime.MaxValue;
foreach (var expression in expressions)
var occurrence = expression.GetNextOccurrence(start);
if (occurrence < nextOccurrence)
nextOccurrence = occurrence;
private static string BuildCronExpression()
var utcNow = DateTime.UtcNow;
const string everyMinute = "*";
var fromHour = utcNow.Hour;
var toHour = utcNow.AddHours(4).Hour;
var fromDayOfMonth = utcNow.Day;
var toDayOfMonth = utcNow.AddHours(4).Day;
var fromMonth = utcNow.ToString("MMM").ToUpper(CultureInfo.InvariantCulture);
var toMonth = utcNow.AddHours(4).ToString("MMM").ToUpper(CultureInfo.InvariantCulture);
var fromDayOfWeek = utcNow.ToString("ddd").ToUpper(CultureInfo.InvariantCulture);
var toDayOfWeek = utcNow.AddHours(4).ToString("ddd").ToUpper(CultureInfo.InvariantCulture);
return $"{everyMinute} {fromHour}-{toHour} {fromDayOfMonth}-{toDayOfMonth} {fromMonth}-{toMonth} {fromDayOfWeek}-{toDayOfWeek}";