给定DateTimeZone和两个Instants,确定LocalTime是否介于两个Instants之间

时间:2013-10-07 12:20:58

标签: c# .net datetime time nodatime

对于我的每个用户,我存储了tzid,我将其转换为DateTimeZone,其中包含有关其当地时区的信息。

我想在当地时间上午8点向用户发送每日电子邮件;如果上午8点因为夏令时转移等原因而模棱两可,我只需选择上午8点之一;我不在乎哪个。

我的工作每小时运行一次,我有一个Instant包含作业的最后一次运行时间,另一个Instant包含作业的下一个运行时间。

鉴于这两个Instant名为previousRunnextRunDateTimeZone名为tz,我如何确定localTime是否eightAM {1}}落在这个工作的范围之间?如果是,我需要向用户发送电子邮件。

1 个答案:

答案 0 :(得分:4)

  

鉴于这两个Instant调用了previousRun和nextRun,而DateTimeZone调用了tz,我如何确定调用了8AM的localTime是否落在这个作业运行的界限之间?

我认为,以一般方式这样做有点棘手。但是,如果你可以依赖你想要远离午夜的时间你的工作将每小时运行一次(所以你不需要考虑如果它会发生什么没有在午夜和早上8点之间运行,例如)我认为你可以这样做:

public static bool ShouldSendEmail(Instant previousRun, Instant nextRun,
                                   DateTimeZone zone)
{
    // Find the instant at which we should send the email for the day containing
    // the last run.
    LocalDate date = previousRun.InZone(zone).Date;
    LocalDateTime dateTime = date + new LocalTime(8, 0);
    Instant instant = dateTime.InZoneLeniently(zone).ToInstant();

    // Check whether that's between the last instant and the next one.
    return previousRun <= instant && instant < nextRun;
}

您可以查看InZoneLeniently的文档以确切地检查它会给出什么结果,但听起来您并不介意:这仍然会每天发送一封电子邮件,一小时内包含上午8点

没有在一天中的时间参数化,因为处理一天中的时间可能接近午夜的一般情况会更难。

编辑:如果您可以存储“下一个发送日期”,那么很容易 - 而且您不需要previousRun部分:

public static bool ShouldSendEmail(LocalDateTime nextDate, Instant nextRun,
                                   DateTimeZone zone, LocalTime timeOfDay)
{
    LocalDateTime nextEmailLocal = nextDate + timeOfDay;
    Instant nextEmailInstant =  nextDateTime.InZoneLeniently(zone).ToInstant();
    return nextRun > nextEmailInstant;
}

基本上说,“当我们下次要发送电子邮件时解决 - 如果下次运行的时间晚于此,我们应该立即发送。”