根据时区在一天中的特定时间安排 Hangfire 作业

2023-12-08

在hangfire中,我可以安排一个作业在特定时间运行延迟调用方法

BackgroundJob.Schedule(
           () => Console.WriteLine("Hello, world"),
           TimeSpan.FromDays(1));

我有一张包含以下信息的表格

    User           Time              TimeZone
    --------------------------------------------------------
    User1          08:00:00           Central Standard Time
    User1          13:00:00           Central Standard Time
    User2          10:00:00           Eastern Standard Time
    User2          17:00:00           Eastern Standard Time
    User3          13:00:00           UTC

鉴于此信息,对于每个用户,我想根据他们的时区每天在配置的时间发送通知

ScheduleNotices方法将在世界标准时间每天上午 12 点运行。此方法将安排当天需要运行的作业。

 public async Task ScheduleNotices()
 {
       var schedules = await _dbContext.GetSchedules().ToListAsync();
       foreach(var schedule in schedules)
       {
          // Given schedule information how do i build enqueueAt that is timezone specific
          var enqueuAt = ??;
          BackgroundJob.Schedule<INotificationService>(x => x.Notify(schedule.User), enqueuAt );
       }
 }

Update 1
The Schedules表信息不断变化。用户可以选择添加/删除时间。我可以创建一个运行每个小步舞曲的重复作业(分钟是hangfire支持的最小单位),然后这个重复作业可以查询Schedules根据时间表发送通知。
然而,数据库交互太多了。所以我只有一项重复工作ScheduleNotices它将在中午 12 点运行(每天一次),并将安排接下来 24 小时的作业。在这种情况下,他们所做的任何更改将从第二天开始生效。


您的答案非常接近。有几个问题:

  • 您假设给定时区的今天与 UTC 的今天相同。根据时区的不同,这些日期可能会有所不同。例如,2019 年 10 月 18 日凌晨 1 点(世界标准时间)是 2019 年 10 月 17 日美国中部时间晚上 8:00。

  • 如果您围绕“今天发生了吗”进行设计,您可能会跳过合法的事件。相反,只考虑“未来下一次发生的事情是什么”会更容易。

  • 您没有采取任何措施来处理无效或不明确的本地时间,例如在 DST 开始或结束以及标准时间更改时发生的情况。这对于重复发生的事件很重要。

接下来是代码:

// Get the current UTC time just once at the start
var utcNow = DateTimeOffset.UtcNow;

foreach (var schedule in schedules)
{
    // schedule notification only if not already scheduled in the future
    if (schedule.LastScheduledDateTime == null || schedule.LastScheduledDateTime.Value < utcNow)
    {
        // Get the time zone for this schedule
        var tz = TimeZoneInfo.FindSystemTimeZoneById(schedule.User.TimeZone);

        // Decide the next time to run within the given zone's local time
        var nextDateTime = nowInZone.TimeOfDay <= schedule.PreferredTime
            ? nowInZone.Date.Add(schedule.PreferredTime)
            : nowInZone.Date.AddDays(1).Add(schedule.PreferredTime);

        // Get the point in time for the next scheduled future occurrence
        var nextOccurrence = nextDateTime.ToDateTimeOffset(tz);

        // Do the scheduling
        BackgroundJob.Schedule<INotificationService>(x => x.Notify(schedule.CompanyUserID), nextOccurrence);

        // Update the schedule
        schedule.LastScheduledDateTime = nextOccurrence;
    }
}

我想你会发现如果你让你的代码和数据更加清晰LastScheduledDateTime a DateTimeOffset?代替DateTime?。上面的代码假设了这一点。如果你don't想要,那么你可以将最后一行更改为:

        schedule.LastScheduledDateTime = nextOccurrence.UtcDateTime;

还要注意使用ToDateTimeOffset,这是一种扩展方法。将其放在某个静态类中。其目的是创建一个DateTimeOffset from a DateTime考虑特定时区。在处理不明确和无效的本地时间时,它应用了典型的调度问题。 (我上次发布了关于它的在另一个 Stack Overflow 答案中如果您想阅读更多内容。)这是实现:

public static DateTimeOffset ToDateTimeOffset(this DateTime dt, TimeZoneInfo tz)
{
    if (dt.Kind != DateTimeKind.Unspecified)
    {
        // Handle UTC or Local kinds (regular and hidden 4th kind)
        DateTimeOffset dto = new DateTimeOffset(dt.ToUniversalTime(), TimeSpan.Zero);
        return TimeZoneInfo.ConvertTime(dto, tz);
    }

    if (tz.IsAmbiguousTime(dt))
    {
        // Prefer the daylight offset, because it comes first sequentially (1:30 ET becomes 1:30 EDT)
        TimeSpan[] offsets = tz.GetAmbiguousTimeOffsets(dt);
        TimeSpan offset = offsets[0] > offsets[1] ? offsets[0] : offsets[1];
        return new DateTimeOffset(dt, offset);
    }

    if (tz.IsInvalidTime(dt))
    {
        // Advance by the gap, and return with the daylight offset  (2:30 ET becomes 3:30 EDT)
        TimeSpan[] offsets = { tz.GetUtcOffset(dt.AddDays(-1)), tz.GetUtcOffset(dt.AddDays(1)) };
        TimeSpan gap = offsets[1] - offsets[0];
        return new DateTimeOffset(dt.Add(gap), offsets[1]);
    }

    // Simple case
    return new DateTimeOffset(dt, tz.GetUtcOffset(dt));
}

(在您的情况下,类型始终是未指定的,因此您可以根据需要删除第一个检查,但我更愿意保持其功能齐全,以防其他用途。)

顺便说一下,你不需要if (!schedules.HasAny()) { return; }查看。实体框架已经测试了期间的更改SaveChangesAsync,如果没有,则不执行任何操作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

根据时区在一天中的特定时间安排 Hangfire 作业 的相关文章

  • 如何将隐藏字段从一个页面传递到另一页面?

    我有一个 Net 类库 我想从一次代码隐藏页面传递一个隐藏变量 并在另一个代码隐藏页面中获取它 请注意 我没有任何可以使用表单标签和 get post 方法的设计页面 aspx 页面 我们应该怎么做 注意 我想使用隐藏字段将值从一页传递到另
  • 为 Visual Studio 2013 编译 Tesseract

    我正在尝试使用tesseract在 Visual Studio 2013 中 我在链接器 gt 输入 不是 libtesseract302 static lib 中使用 libtesseract302 lib 一切都正常 并且已编译并运行
  • 启动时出现 OData v4 错误:找不到段“Whatever”的资源

    我正在构建新的 v4 服务 一切进展顺利 直到我为新模型 实体添加了新控制器 并在启动站点进行测试运行时收到此错误 控制器似乎编码正确 就像其他控制器一样 控制器 CustomersOData 中的操作 GetFeed 上的路径模板 Cus
  • 如何访问另一个窗体上的ListView控件

    当单击与 ListView 所在表单不同的表单中的按钮时 我试图填充 ListView 我在 Form1 中创建了一个方法以在 Form2 中使用 并将参数传递给 Form1 中的方法 然后填充 ListView 当我调试时 我得到了传递的
  • C++中的类查找结构体数组

    我正在尝试创建一个结构数组 它将输入字符串链接到类 如下所示 struct string command CommandPath cPath cPathLookup set an alarm AlarmCommandPath send an
  • 无法在 Windows 运行时组件库的 UserControl 中创建依赖项属性

    我想在用户控件内创建数据可绑定属性 这个用户控件包含一个 Windows 运行时组件 项目 我使用下面的代码来创建属性 public MyItem CurrentItem get return MyItem GetValue Current
  • 在一个字节中存储 4 个不同的值

    我有一个任务要做 但我不知道从哪里开始 我不期待也绝对不想要代码中的答案 我想要一些关于该怎么做的指导 因为我感到有点失落 将变量打包和解包到一个字节中 您需要在一个字节中存储 4 个不同的值 这些值为 NAME RANGE BITS en
  • 如何将自定义 JSON 文件添加到 IConfiguration 中?

    我正在使用 asp net Autofac 我正在尝试加载自定义 JSON 配置文件 并基于该文件创建 实例化 IConfiguration 实例 或者至少将我的文件包含到默认情况下构建的 IConfiguration asp net 中
  • 如何对 Web Api 操作进行后调用?

    我创建了一个 Web API 操作 如下所示 HttpPost public void Load string siteName string providerName UserDetails userDetails implementat
  • 如何在按钮单击时模拟按键 - Unity

    我对 Unity 中的脚本编写非常陌生 我正在尝试创建一个按钮 一旦单击它就需要模拟按下 F 键 要拾取一个项目 这是我当前的代码 在编写此代码之前我浏览了所有统一论坛 但找不到任何有效的东西 Code using System Colle
  • 有没有办法强制显示工具提示?

    我有一个验证字段的方法 如果无法验证 该字段将被清除并标记为红色 我还希望在框上方弹出一个工具提示 并向用户显示该值无效的消息 有没有办法做到这一点 并且可以控制工具提示显示的时间 我怎样才能让它自己弹出而不是鼠标悬停时弹出 If the
  • 线程和 fork()。我该如何处理呢? [复制]

    这个问题在这里已经有答案了 可能的重复 多线程程序中的fork https stackoverflow com questions 1235516 fork in multi threaded program 如果我有一个使用 fork 的
  • memset 未填充数组

    u32 iterations 5 u32 ecx u32 malloc sizeof u32 iterations memset ecx 0xBAADF00D sizeof u32 iterations printf 8X n ecx 0
  • Linq-to-entities,在一个查询中获取结果+行数

    我已经看到了有关此事的多个问题 但它们已经有 2 年 或更长 的历史了 所以我想知道这方面是否有任何变化 基本思想是填充网格视图并创建自定义分页 所以 我还需要结果和行数 在 SQL 中 这将类似于 SELECT COUNT id Id N
  • 如何将 Roslyn 语义模型返回的类型符号名称与 Mono.Cecil 返回的类型符号名称相匹配?

    我有以下代码 var paramDeclType m semanticModel GetTypeInfo paramDecl Type Type Where paramDeclType ToString returns System Col
  • 检查Windows控制台中是否按下了键[重复]

    这个问题在这里已经有答案了 可能的重复 C 控制台键盘事件 https stackoverflow com questions 2067893 c console keyboard events 我希望 Windows 控制台程序在按下某个
  • 当另一个线程可能设置共享布尔标志(最多一次)时,是否可以读取共享布尔标志而不锁定它?

    我希望我的线程能够更优雅地关闭 因此我尝试实现一个简单的信号机制 我不认为我想要一个完全事件驱动的线程 所以我有一个工作人员有一种方法可以使用关键部分优雅地停止它Monitor 相当于C lock我相信 绘图线程 h class Drawi
  • 如何使用 Word Automation 获取页面范围

    如何使用办公自动化找到 Microsoft Word 中第 n 页的范围 似乎没有 getPageRange n 函数 并且不清楚它们是如何划分的 这就是您从 VBA 执行此操作的方法 转换为 Matlab COM 调用应该相当简单 Pub
  • 在客户端系统中安装后桌面应用程序无法打开

    我目前正在使用 Visual Studio 2017 和 4 6 1 net 框架 我为桌面应用程序创建了安装文件 安装程序在我的系统中完美安装并运行 问题是安装程序在其他计算机上成功安装 但应用程序无法打开 edit 在客户端系统中下载了
  • 如何正确使用 std::condition_variable?

    我很困惑conditions variables以及如何 安全 使用它们 在我的应用程序中 我有一个创建 gui 线程的类 但是当 gui 是由 gui 线程构造时 主线程需要等待 情况与下面的函数相同 主线程创建互斥体 锁和conditi

随机推荐

  • 是否有与 ASP.NET 的 PrimeFaces 等效的东西?

    我多年来一直是 ASP NET 开发人员 但最近我开始使用 JSF 2 0 来使用一些 PrimeFaces 解决方案 我对此没有什么可抱怨的 值得的强调几点让我喜欢PrimeFaces的 许多组件 易于使用 完全基于 jQuery 和 j
  • 如何用R将非方阵转换为方阵?

    我有一个网络数据并试图对其进行分析 问题是它缺少一些行或列 我想匹配行和列 所以它可以是方阵 我的数据如下所示 A B C D E A 0 2 1 4 5 B 1 0 2 4 2 D 2 4 0 2 2 E 1 2 2 2 0 我想让它看起
  • 在参数评估顺序中警告 UB

    我最近在这样的代码中遇到了一个错误 class C public foo return value depends on C s state AND each call to foo changes the state int foo in
  • setOnItemClickListener 没有响应[重复]

    这个问题在这里已经有答案了 可能的重复 setOnItemClickListener 没有被调用 我有一个扩展基本适配器的自定义适配器 当我在 onCreate 中设置 setOnItemClickListener 并实现 onItemCl
  • 有没有办法让 Perl 正则表达式搜索不区分大小写?

    Example my cities qr San Francisco Los Angeles 标量 cities将匹配San Francisco and Los Angeles但不会匹配SAN FRANCISCO LOS ANGELES s
  • 覆盖 Django 表单的默认属性

    在我的 Django 应用程序中 我有几种不同的表单 它们的风格相似 为了不一遍又一遍地重复自己 我尝试重写默认的表单设置 首先 我想为我在应用程序中使用的每个表单设置一些默认设置 并尝试将其子类化django forms Form cla
  • 检测传单是否放大或缩小

    我如何知道用户何时放大或缩小 如果用户在一定级别后缩放 我想启动动画 当事件zoomstart被触发时是否可以知道这一点 我如何知道用户何时放大或缩小 在每zoom水平 计算多少map getZoom 已经改变 当事件zoomstart被触
  • 无法再连接到本地 SQL Server 2008 数据库

    今天我去连接到本地数据库 但由于未知原因无法再连接 我像往常一样输入 本地 并使用 Windows 身份验证 但出现此错误 无法连接到本地主机 发生网络相关或特定于实例的错误 建立与 SQL 的连接 服务器 找不到服务器或 无法访问 验证
  • 如何更改 ServiceStack 中的默认 ContentType?

    I have 注册了新的内容类型在 ServiceStack 中 appHost ContentTypeFilters Register application x my content type SerializeToStream Des
  • C++ 中 std::cin 对象的规则是什么?

    我正在编写一个小程序供我个人使用 用于练习学习 C 及其功能 即 MLA 引文生成器 我正在写一篇包含数十次引用的大型论文 由于缺乏更好的方法来做到这一点 我不理解类或在主程序中使用其他 cpp 文件 所以不用费心告诉我 当我有更多时间时我
  • 为什么 git track 我桌面上的所有新文件?

    我有一个 问题 当我在桌面上创建 或下载 任何文件夹 文件时 Git 该轨道 这是为什么 这是正常还是不正常 O S Windows 10 Git version latest at this moment 好吧 当我打开 VS 代码时 代
  • 水平滚动网格视图

    我知道在 Android 中不可能水平滚动网格视图 但我正在做的是在水平滚动视图中动态添加图像按钮 如下所示 public class HorizontalScroller extends Activity static int l 0 p
  • 表达式混合:为什么我没有过渡和缓动选项?

    我正在使用带有 Net 3 5 的 Expression Blend 4 在下图中 有过渡效果选项以及为过渡选择缓动效果的功能 我的 Blend 界面在我的 WPF 应用程序上没有这些 但是 如果我创建一个新应用程序 例如 WPF Sket
  • 当您已经拥有主分支时,如何从存储库派生新分支?

    我已经将一个存储库分叉到我自己的 github 帐户中 并成功将其拉到我的电脑上 但是现在原始存储库上有一个我想要的新分支 但是当我尝试分叉该分支时 它会将我带到主分支在我的 github 帐户上 实际上没有做任何事情 我如何在我的帐户上获
  • 深度学习中可能/也许的类别

    我有兴趣利用我在深度学习任务中拥有的一些部分标记的数据 我使用的是完全卷积方法 而不是从标记区域中采样补丁 我有一些掩模 可以勾勒出图像中明确的正例区域 但图像中未掩模的区域不一定是负的 它们可能是正的 有谁知道如何将此类课程融入深度学习环
  • 与 SQLAlchemy、SQLite 比较日期

    我正在编写一个使用 SQLAlchemy 和 SQLite 数据库的应用程序 我相信我的数据库 表和映射配置正确 因为其他操作按预期工作 我正在尝试编写一个函数 用于检索其日期字段与作为函数参数提供的 datetime date 相匹配的所
  • JSF 应用程序中可添加书签的 URL - 尝试使用 Spring Webflow 和 JSF。有什么建议么?

    您的应用程序是 JSF hibernate 和 Spring 目前 url 的格式如下 我们想要一个干净的网址 例如http www skill guru com urltitle some范围 我们可以实现此目的的方法之一是通过将 Spr
  • 从 ASP.NET GridView 获取 DataRow

    我有一个 ASP NETGridView这绑定到一个ObjectDataSource 绑定到MySQL数据库 在这个网格上 我有 2 个未绑定的ButtonField我想要触发服务器端事件的列 因此我添加了一个事件处理程序方法GridVie
  • 如何使用 C# 打印文本文件 [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 如何在 C 中打印文本文件 在控制台应用程序中 这是我发现的 msdn样本和这个stackoverflow 答案是msdn示例 链接中的代码适用于 Windows 窗体应用程序 不适
  • 根据时区在一天中的特定时间安排 Hangfire 作业

    在hangfire中 我可以安排一个作业在特定时间运行延迟调用方法 BackgroundJob Schedule gt Console WriteLine Hello world TimeSpan FromDays 1 我有一张包含以下信息