Skip to content

Commit

Permalink
FixBug:NbCronExpression在Cron表达时有小时设置时会有时区不下正确的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
fish-li committed Dec 12, 2023
1 parent b428055 commit 5af35dc
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 48 deletions.
4 changes: 2 additions & 2 deletions src/ClownFish.Email/ClownFish.Email.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<RootNamespace>ClownFish.Email</RootNamespace>
<AssemblyVersion>8.0.0.0</AssemblyVersion>
<Version>8.0.1208.2</Version>
<FileVersion>8.0.1208.2</FileVersion>
<Version>8.0.1212.1</Version>
<FileVersion>8.0.1212.1</FileVersion>
<SatelliteResourceLanguages>xx</SatelliteResourceLanguages>
<OutputPath>bin</OutputPath>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
Expand Down
4 changes: 2 additions & 2 deletions src/ClownFish.ImClients/ClownFish.ImClients.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<RootNamespace>ClownFish.ImClients</RootNamespace>
<AssemblyVersion>8.0.0.0</AssemblyVersion>
<Version>8.0.1208.2</Version>
<FileVersion>8.0.1208.2</FileVersion>
<Version>8.0.1212.1</Version>
<FileVersion>8.0.1212.1</FileVersion>
<SatelliteResourceLanguages>xx</SatelliteResourceLanguages>
<OutputPath>bin</OutputPath>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
Expand Down
4 changes: 2 additions & 2 deletions src/ClownFish.Office/ClownFish.Office.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<RootNamespace>ClownFish.Office</RootNamespace>
<AssemblyVersion>8.0.0.0</AssemblyVersion>
<Version>8.0.1208.2</Version>
<FileVersion>8.0.1208.2</FileVersion>
<Version>8.0.1212.1</Version>
<FileVersion>8.0.1212.1</FileVersion>
<SatelliteResourceLanguages>xx</SatelliteResourceLanguages>
<OutputPath>bin</OutputPath>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
Expand Down
4 changes: 2 additions & 2 deletions src/ClownFish.Rabbit/ClownFish.Rabbit.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<RootNamespace>ClownFish.Rabbit</RootNamespace>
<AssemblyVersion>8.0.0.0</AssemblyVersion>
<Version>8.0.1208.2</Version>
<FileVersion>8.0.1208.2</FileVersion>
<Version>8.0.1212.1</Version>
<FileVersion>8.0.1212.1</FileVersion>
<SatelliteResourceLanguages>xx</SatelliteResourceLanguages>
<OutputPath>bin</OutputPath>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
Expand Down
4 changes: 2 additions & 2 deletions src/ClownFish.Redis/ClownFish.Redis.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<RootNamespace>ClownFish.NRedis</RootNamespace>
<AssemblyVersion>8.0.0.0</AssemblyVersion>
<Version>8.0.1208.2</Version>
<FileVersion>8.0.1208.2</FileVersion>
<Version>8.0.1212.1</Version>
<FileVersion>8.0.1212.1</FileVersion>
<SatelliteResourceLanguages>xx</SatelliteResourceLanguages>
<OutputPath>bin</OutputPath>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
Expand Down
4 changes: 2 additions & 2 deletions src/ClownFish.Tracing/ClownFish.Tracing.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<RootNamespace>ClownFish.Tracing</RootNamespace>
<AssemblyVersion>8.0.0.0</AssemblyVersion>
<Version>8.0.1208.2</Version>
<FileVersion>8.0.1208.2</FileVersion>
<Version>8.0.1212.1</Version>
<FileVersion>8.0.1212.1</FileVersion>
<OutputType>Library</OutputType>
<SatelliteResourceLanguages>xx</SatelliteResourceLanguages>
<OutputPath>bin</OutputPath>
Expand Down
4 changes: 2 additions & 2 deletions src/ClownFish.Web/ClownFish.Web.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<RootNamespace>ClownFish.Web</RootNamespace>
<AssemblyVersion>8.0.0.0</AssemblyVersion>
<Version>8.0.1208.2</Version>
<FileVersion>8.0.1208.2</FileVersion>
<Version>8.0.1212.1</Version>
<FileVersion>8.0.1212.1</FileVersion>
<SatelliteResourceLanguages>xx</SatelliteResourceLanguages>
<OutputPath>bin</OutputPath>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
Expand Down
4 changes: 2 additions & 2 deletions src/ClownFish.net/ClownFish.net.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<TargetFrameworks>net48;net6.0;net7.0;net8.0</TargetFrameworks>
<RootNamespace>ClownFish</RootNamespace>
<AssemblyVersion>8.0.0.0</AssemblyVersion>
<Version>8.0.1208.2</Version>
<FileVersion>8.0.1208.2</FileVersion>
<Version>8.0.1212.1</Version>
<FileVersion>8.0.1212.1</FileVersion>
<SatelliteResourceLanguages>xx</SatelliteResourceLanguages>
<OutputPath>bin</OutputPath>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
Expand Down
20 changes: 13 additions & 7 deletions src/ClownFish.net/Tasks/NbCronExpression.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#if NETCOREAPP

using Cronos;
//using Quartz;
namespace ClownFish.Tasks;


Expand All @@ -10,22 +11,27 @@ internal sealed class NbCronExpression

public NbCronExpression(string expression)
{
_cronExpression = CronExpression.Parse(expression, Cronos.CronFormat.IncludeSeconds);
_cronExpression = Cronos.CronExpression.Parse(expression, Cronos.CronFormat.IncludeSeconds);

//_cronExpression = new Quartz.CronExpression(expression);
}

public DateTime? GetNextUtcTime(DateTime dateTime)
{
return _cronExpression.GetNextOccurrence(dateTime.ToUniversalTime());
return _cronExpression.GetNextOccurrence(dateTime.ToUniversalTime()); // Cronos

//DateTimeOffset? next = _cronExpression.GetNextValidTimeAfter(dateTime); // Quartz
//return next?.DateTime;
}


public DateTime? GetNextLocalTime(DateTime dateTime)
{
DateTime? value = GetNextUtcTime(dateTime);
if( value.HasValue == false )
return null;
else
return value.Value.ToLocalTime();
DateTimeOffset? next = _cronExpression.GetNextOccurrence(new DateTimeOffset(dateTime), TimeZoneInfo.Local); // Cronos
return next?.DateTime;

//DateTimeOffset? next = _cronExpression.GetNextValidTimeAfter(dateTime); // Quartz
//return next?.DateTime.ToLocalTime();
}
}
#endif
3 changes: 2 additions & 1 deletion test/ClownFish.UnitTest/ClownFish.UnitTest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
<PackageReference Include="dmdbms.DmProvider" Version="1.1.3" />
<PackageReference Include="Quartz" Version="3.4.0" />
<PackageReference Include="Quartz" Version="3.8.0" />
<PackageReference Include="Cronos" Version="0.7.1" />
</ItemGroup>

<ItemGroup>
Expand Down
108 changes: 84 additions & 24 deletions test/ClownFish.UnitTest/Tasks/CronExpressionTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,69 +7,104 @@
public class CronExpressionTest
{
[TestMethod]
public void Test()
public void Test_1()
{
string cronValue = "0/5 * * * * ? ";
DateTime start = DateTime.Now;
int count = 100;

string s1 = Test1(cronValue, start, count);
string s2 = Test2(cronValue, start, count);
string s3 = Test3(cronValue, start, count);

Console.WriteLine(s1);
Assert.AreEqual(s1, s2);
Assert.AreEqual(s1, s3);
string[] cronArray = new string[] { "0/5 * * * * ?" , // 每 5 秒执行一次
"0 0 1 * * ?" , // 每天 1:00 执行一次
"0 30 14 ? * FRI" , // 每天 14:30 执行一次
"0/2 * * * * ?", // 表示每2秒 执行任务
"0 0/2 * * * ?", // 表示每2分钟 执行任务
"0 0 2 1 * ?", // 表示在每月的1日的凌晨2点调整任务
"0 15 10 ? * MON-FRI", // 表示周一到周五每天上午10:15执行作业
"0 0 10,14,16 * * ?", // 每天上午10点,下午2点,4点
"0 0/30 9-17 * * ?", // 朝九晚五工作时间内每半小时
"0 0 12 ? * WED", // 表示每个星期三中午12点
"0 0 12 * * ?", // 每天中午12点触发
"0 15 10 ? * *", // 每天上午10:15触发
"0 15 10 * * ?", // 每天上午10:15触发
//"0 15 10 * * ? 2005", // 2005年的每天上午10:15触发
"0 * 14 * * ?", // 在每天下午2点到下午2:59期间的每1分钟触发
"0 0/5 14 * * ?", // 在每天下午2点到下午2:55期间的每5分钟触发
"0 0/5 14,18 * * ?", // 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
"0 0-5 14 * * ?", // 在每天下午2点到下午2:05期间的每1分钟触发
"0 10,44 14 ? 3 WED", // 每年三月的星期三的下午2:10和2:44触发
"0 15 10 ? * MON-FRI", // 周一至周五的上午10:15触发
"0 15 10 15 * ?", // 每月15日上午10:15触发
"0 15 10 L * ?", // 每月最后一日的上午10:15触发
//"0 15 10 ? * 6L", // 每月的最后一个星期五上午10:15触发
//"0 15 10 ? * 6L 2002-2105",// 2002年至2005年的每月的最后一个星期五上午10:15触发
//"0 15 10 ? * 6#3", // 每月的第三个星期五上午10:15触发
// copy from https://cron.qqe2.com/
// 注意:对于 “day of week 1-7” ,Quartz和Cronos的解释不一样,前者是:SUN-SAT,后者是 MON-SUN
};


foreach( string cronValue in cronArray ) {
Console.WriteLine("-------------------------------");
Console.WriteLine(cronValue);

DateTime start = DateTime.Now;
int count = 10;

string s1 = Test_Quartz(cronValue, start, count);
string s2 = Test_Cronos(cronValue, start, count);
string s3 = Test_NbCron(cronValue, start, count);

Console.WriteLine(s1);

Assert.AreEqual(s1, s2);
Assert.AreEqual(s1, s3);
}
}

private string Test1(string cronValue, DateTime start, int count)
private string Test_Quartz(string cronValue, DateTime start, int count)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine(start.ToTimeString());
sb.AppendLine(start.ToTimeString() + "---now");

Quartz.CronExpression cron = new Quartz.CronExpression(cronValue);

DateTimeOffset current = new DateTimeOffset(start);

for( int i = 0; i < count; i++ ) {
DateTimeOffset? next = cron.GetNextValidTimeAfter(current);
sb.AppendLine(next.Value.DateTime.ToTimeString());
sb.AppendLine(next.Value.DateTime.ToLocalTime().ToTimeString()); // 使用“本地时区”

current = next.Value;
}
return sb.ToString();
}

private string Test2(string cronValue, DateTime start, int count)
private string Test_Cronos(string cronValue, DateTime start, int count)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine(start.ToTimeString());
sb.AppendLine(start.ToTimeString() + "---now");

Cronos.CronExpression cron = Cronos.CronExpression.Parse(cronValue, Cronos.CronFormat.IncludeSeconds);

DateTime current = start;
DateTimeOffset current = new DateTimeOffset(start);

for( int i = 0; i < count; i++ ) {
DateTime? next = cron.GetNextOccurrence(current.ToUniversalTime());
sb.AppendLine(next.Value.ToTimeString());
DateTimeOffset? next = cron.GetNextOccurrence(current, TimeZoneInfo.Local); // 使用“本地时区”
sb.AppendLine(next.Value.DateTime.ToTimeString());

current = next.Value;
}

return sb.ToString();
}

private string Test3(string cronValue, DateTime start, int count)
private string Test_NbCron(string cronValue, DateTime start, int count)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine(start.ToTimeString());
sb.AppendLine(start.ToTimeString() + "---now");

NbCronExpression cron = new NbCronExpression(cronValue);

DateTime current = start;
DateTime current = start;

for( int i = 0; i < count; i++ ) {
DateTime? next = cron.GetNextUtcTime(current);
DateTime? next = cron.GetNextLocalTime(current); // 使用“本地时区”
sb.AppendLine(next.Value.ToTimeString());

current = next.Value;
Expand All @@ -79,5 +114,30 @@ private string Test3(string cronValue, DateTime start, int count)
}


[TestMethod]
public void Test_2()
{
Console.WriteLine("Now: " + DateTime.Now.ToTimeString());

ShowNext10TimeValue("0/5 * * * * ?");
Console.WriteLine("---------------------------------");
ShowNext10TimeValue("0 0 1 * * ?");
Console.WriteLine("---------------------------------");
ShowNext10TimeValue("0 30 14 ? * FRI");
}

private void ShowNext10TimeValue(string cronValue)
{
NbCronExpression cron = new NbCronExpression(cronValue);

DateTime current = DateTime.Now;

for( int i = 0; i <= 10; i++ ) {
DateTime? next = cron.GetNextLocalTime(current);
Console.WriteLine(next.Value.ToTimeString());
current = next.Value;
}
}

}
#endif

0 comments on commit 5af35dc

Please sign in to comment.