【问题标题】:How to get datetime in specific TimeZone for Scheduler如何为调度程序获取特定时区的日期时间
【发布时间】:2013-10-21 22:02:32
【问题描述】:

背景:

我正在尝试安排一项任务,以便在项目中向我的用户发送邮件。我想通过在凌晨 2 点发送邮件来自动执行此任务。美国东部标准时间每天。

我的代码:

我真的想不出一个好的代码,但我正在这样做:

 DateTime.Now.AddHours(hours);

但问题是,当我将此代码部署到服务器时,它需要 DateTime.Now 即部署时间并将 hours 添加到该时间。

我怎样才能找到一个干净的解决方案?

【问题讨论】:

标签: c# asp.net asp.net-mvc datetime


【解决方案1】:

要使用当地时间,您需要时区:

var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

要获取您以当地时间表示的计划时间,您需要获取当前当地时间并决定下一次计划的时间:

var estNow = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, timeZoneInfo);
var estScheduleAt = estNow.Date + TimeSpan.FromHours(2);

现在estScheduleAt 将是美国东部标准时间今天凌晨 2 点。如果此代码在美国东部标准时间上午 12 点到凌晨 2 点之间执行,您应该在此时安排下一个操作。但是,如果当前时间在美国东部标准时间凌晨 2 点之后,您应该安排在明天凌晨 2 点(仍在美国东部标准时间),因此您需要在时间上增加一天:

if (estScheduleAt <= estNow)
  estScheduleAt += TimeSpan.FromDays(1);

如果该算法在美国东部标准时间凌晨 2 点之前运行,则该算法可能会失败,因为谓词 estScheduleAt &lt;= estNow 为真,但在计划操作之前它已经过去了。您可能需要针对这种情况添加一些额外的处理。

在安排操作之前,您应该转换回 UTC 以避免任何时区问题:

var scheduleAt = TimeZoneInfo.ConvertTimeToUtc(estScheduleAt, timeZoneInfo);

现在您可以在调度程序中使用scheduleAt 时间戳,让您的操作在美国东部标准时间的下一个凌晨 2 点运行。

【讨论】:

  • 您能否解释一下您在 if 语句中所做的事情:if (estScheduleAt &lt;= estNow) estScheduleAt += TimeSpan.FromDays(1);
  • @BhushanFirake:我已经扩展了我的答案。
  • 好答案。但是您还需要注意夏令时转换日期。例如,在 2013 年 3 月 10 日,凌晨 2:00 没有发生,如果您安排在凌晨 1:00,那么您会在 2013 年 11 月 3 日发现它发生了 两次。见herehere
【解决方案2】:

我已经完成了Quartz.Net scheduler

对于配置,我使用 CronMaker 作为表达式

示例代码

// construct a scheduler factory
ISchedulerFactory schedFact = new StdSchedulerFactory();

// get a scheduler
IScheduler sched = schedFact.GetScheduler();
sched.Start();

// construct job info
JobDetail jobDetail = new JobDetail("myJob", null, typeof(HelloJob));
// fire every hour
Trigger trigger = TriggerUtils.MakeHourlyTrigger();
// start on the next even hour
trigger.StartTimeUtc = TriggerUtils.GetEvenHourDate(DateTime.UtcNow);  
trigger.Name = "myTrigger";
sched.ScheduleJob(jobDetail, trigger); 

查看Quartz.net setup in an asp.net website

【讨论】:

  • 我不想使用 Quartz.net,我只想让 datetime 准确安排
【解决方案3】:

使用 DateTime.UtcNow 并为其添加小时数。

最好在 UTC 时间执行所有操作,然后在代码入口和出口点将其转换为本地时间。

【讨论】:

  • 我不能使用裸DateTime吗?
  • @BhushanFirake:如果您 bare DateTime 的意思是使用 DateTime.Now 而不是 DateTime.UtcNow,那么,不,这是个坏主意。 DateTime.Now 反映了运行代码的服务器的时区,它可能与您需要使用的时区 EST 不同。
  • @MartinLiversage 是的,只是吞没了那个...... :)
猜你喜欢
  • 2016-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-23
  • 1970-01-01
  • 1970-01-01
  • 2020-03-27
  • 1970-01-01
相关资源
最近更新 更多