运行 Quartz 作业时补偿时区偏移

2024-01-28

我有一个独特的问题,因为我的quartz作业调度程序实现是使用quartz.net代码库版本2.0.1构建的,最近发现在运行和执行作业时时区和utc偏移量被忽略。这是该版本quartz.net 中的一个继承错误,更新到版本 2.1.1 目前超出了范围,因此我编写了一种使用此算法计算偏移量的快速而肮脏的方法:

(服务器时间 - 客户端时间) - 目标时间 = New_TargetTime_With_Offset

这里的想法是,位于纽约的客户在下午 5:00 完成一项工作,并希望它在下午 2:00 运行。服务器(运行此应用程序和作业服务器的地方)当前时间为下午 2:00,因此我们使用客户端时间和服务器时间来获取偏移量,并将该偏移量应用于目标时间,即作业应运行的时间。

我的问题是,这感觉像是一种计算日期的迂回方式,但看起来它可以完成这项工作。有没有更好/更可靠的方法来进行这个日期数学?另外,这在边缘情况下似乎是有问题的,我错过了什么?

这是实现:

    /// <summary>
    /// Takes three dates and returns the adjusted hour value.
    /// All date data is ignored except for the hour. 
    /// </summary>
    /// <param name="serverTime"></param>
    /// <param name="clientTime"></param>
    /// <param name="targetTime"></param>
    /// <returns></returns>
    private static DateTime OutputDate(DateTime serverTime, DateTime clientTime, DateTime targetTime)
    {
        DateTime? output = null;
        TimeSpan? dateDiff;

        if (serverTime < clientTime)
        {
            dateDiff = (clientTime - serverTime);
        }
        else
        {
            dateDiff = (serverTime - clientTime);
        }

        output = (targetTime - dateDiff);

        return output.Value;
    }

以下是利用它的两个示例:

    /// <summary>
    /// -5 Offset (NYC)
    /// </summary>
    /// <returns></returns>
    private static Int32 ZoneTest001()
    {
        var targetTime = DateTime.Parse("6/12/2013 5:00PM");  // NYC (est) [The time the report should be received in NYC]
        var clientTime = DateTime.Parse("6/12/2013 5:00PM");   // NYC (est) [The time of the client when the report is created (now) ]
        var serverTime = DateTime.Parse("6/12/2013 2:00PM");  // SEA (pst) [The time of the app server when the report is created (now) ]

        //
        // NYC Wants to send a report at 5:00pm EST
        // The server time will be 2:00pm PST
        // The client time will be 5:00pm EST

        double outputHour = 0;   // should end up as 2:00pm PST

        //
        // 1) Get offset (diff between client & server time)
        // 2) Subtract offset from "targetTime"
        // 3) Set the report to be sent at the new hour value.

        outputHour = OutputDate(serverTime, clientTime, targetTime).Hour;

        return (int)outputHour;

    }

    /// <summary>
    /// +5 Offset (India)
    /// </summary>
    /// <returns></returns>
    private static Int32 ZoneTest002()
    {
        var targetTime = DateTime.Parse("6/12/2013 5:00PM"); // IND (ist)
        var clientTime = DateTime.Parse("6/12/2013 9:00AM");  // IND (ist)
        var serverTime = DateTime.Parse("6/12/2013 2:00PM"); // SEA (pst)

        //
        // INDIA Wants to send a report at 5:00pm IST
        // The server time will be 2:00pm PST
        // The client time will be 9:00am PST

        double outputHour = 0;   // should end up as 2:00pm PST
        outputHour = OutputDate(serverTime, clientTime, targetTime).Hour;

        return (int)outputHour;

    }

谢谢。


实际上你错过了很多。

  1. 时区偏移量不是恒定的。许多时区会切换夏令时(又称“夏令时”)的偏移量。因此,当您根据每个位置(服务器、客户端、目标)的“现在”计算偏移量时,这仅反映了current offset.

  2. 在任何有 DST 的时区,当时钟向前滚动时,都会缺少一个小时,并且重复的时钟向后滚动的小时。如果您正在处理当地时间,并且预定的事件属于不明确的时间段,则您无法确定运行该事件的实际时刻。为了消除歧义,您需要told对应的偏移量是多少,或者你需要以UTC来处理。

  3. 如果您要从一个时区转换到另一个时区,则需要处理时区,而不仅仅是它们的偏移量。在.Net中,您可以使用内置的Windows时区数据库和相应的TimeZoneInfo班级。或者,您可以使用更标准的 IANA 时区数据库,例如野田时间 http://www.nodatime.org.

  4. 当与DateTime类型,要非常小心.Kind属性设置为。许多函数在处理不同类型时有不同的行为。使用该方法会更安全、更有用DateTimeOffset改为键入。

  5. 您真的不应该依赖于代码运行的服务器的时区。服务器代码应该与时区无关。你唯一应该参与的地方DateTime.Now or TimeZoneInfo.Local或任何类似的功能在desktop or mobile应用程序。服务器代码应该仅取决于 UTC。

  6. 我真的不明白为什么你的内部有可为空的值OutputDate方法。没有理由这样做。此外,您实际上正在获取差异的绝对值 - 这会降低方向性。时区偏移确实是定向的,因此您当前的实现可能会得到无效的结果。

  7. 我查看了 Quartz.net API,他们似乎更喜欢您在 UTC 中安排活动时间。这是一件非常好的事情,因为 UTC 不存在歧义问题。来自Quartz.Net 教程 http://quartznet.sourceforge.net/tutorial/lesson_1.html, the trigger.StartTimeUtc显然是UTCDateTime。既然你说你不能使用最新版本,我还检查了他们较旧的1.0 API文档,它仍然是UTC。

    Update: 石英网2.5 https://www.quartz-scheduler.net/2017/02/18/quartznet-2.5-released.html更大可以更好地处理时区。看#317 https://github.com/quartznet/quartznet/pull/317了解详情。

让我们将所有这些放在一起作为您的示例用例。纽约市的一位客户希望在当地时区的下午 2:00 运行作业。服务器的时区无关紧要,他创建作业的时间也无关紧要。

// June 6, 2013 2:00 PM  Kind = Unspecified
DateTime dt = new DateTime(2013, 6, 13, 14, 0, 0);

// This is the correct Windows time zone for New York
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

// Get the time in UTC - The kind matters here.
DateTime utc = TimeZoneInfo.ConvertTimeToUtc(dt, tz);

// Feed it to a quartz event trigger
trigger.StartTimeUtc = utc;

当我在第三步中将时间转换为 UTC 时,如果时间不明确,.Net 会假设您想要standard时间而不是daylight时间。如果您想更具体,则必须检查是否有歧义,然后询问用户他们想要两个当地时间中的哪一个。那么你就必须使用DateTimeOffset以区分它们。如果您认为您可能需要这个,请告诉我,我可以制作一个样本,但它有点复杂。

为了更好地衡量,如果您想使用 IANA 时区野田时间 http://www.nodatime.org,它看起来像这样:

LocalDateTime ldt = new LocalDateTime(2013, 6, 13, 14, 0);
DateTimeZone tz = DateTimeZoneProviders.Tzdb["America/New_York"];
ZonedDateTime zdt = ldt.InZoneLeniently(tz);
trigger.StartTimeUtc = zdt.ToDateTimeUtc();

The InZoneLeniently方法将给出与上面代码相​​同的行为。但如果需要,您还可以指定其他选项。

哦,这并不重要,但印度是+5:30, not +5

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

运行 Quartz 作业时补偿时区偏移 的相关文章

  • 聚合日期时间以总结在特定条件下花费的时间

    我很困惑我应该如何继续 我下面有一些虚拟数据 Date lt as POSIXct c 2018 03 20 11 52 25 2018 03 22 12 01 44 2018 03 20 12 05 25 2018 03 20 12 10
  • 在 C/C++ 中获得正模数的最快方法

    通常在我的内部循环中 我需要以 环绕 方式索引数组 因此 例如 如果数组大小为 100 并且我的代码要求元素 2 则应该给它元素 98 高级语言 例如 Python 可以简单地使用my array index array size 但由于某
  • 何时使用 =default 使析构函数默认?

    尽管对构造函数使用 default 对我来说很清楚 即强制编译器在其他构造函数存在时创建默认构造函数 但我仍然无法理解这两种类型的析构函数之间的区别 那些使用 default 的 那些没有显式定义并由编译器自动生成的 我唯一想到的是 gro
  • FileStream 构造函数和默认缓冲区大小

    我们有一个使用 NET 4 用 C 编写的日志记录类 我想添加一个构造函数参数 该参数可以选择设置文件选项 WriteThrough http msdn microsoft com en us library system io fileo
  • 在 Xamarin 中隐藏软键盘

    如何隐藏软键盘以便在聚焦时显示Entry在 Xamarin forms 便携式表单项目中 我假设我们必须为此编写特定于平台的渲染器 但以下内容不起作用 我创建自己的条目子类 public class MyExtendedEntry Entr
  • 防止 boost::asio::io_context 在空轮询调用时停止

    此代码调用发布的句柄 boost asio io context ioc boost asio post ioc std cout lt lt lol lt lt std endl ioc poll 而这并没有 boost asio io
  • 与 Qt 项目的静态链接

    我有一个在 Visual Studio 2010 Professional 中构建的 Qt 项目 但是 当我运行它 在调试或发布模式下 时 它会要求一些 Qt dll 如果我提供 dll 并将它们放入 System32 中 它就可以工作 但
  • fprintf() 线程安全吗?

    我正在为野人就餐问题的某些变量编写一个 C 解决方案 现在 我创建线程 每个线程都将 FILE 获取到同一个调试文件 在线程内我正在使用 fprintf 进行一些打印 打印的语句不受任何类型的互斥锁等保护 我没有在调试文件中观察到任何交错行
  • 单例模式和 std::unique_ptr

    std unique ptr唯一地控制它指向的对象 因此不使用引用计数 单例确保利用引用计数只能创建一个对象 那么会std unique ptr与单例执行相同 单例确保只有一个实例属于一种类型 A unique ptr确保只有一个智能指针到
  • 在 JSQMessagesViewController 中显示 LocationMediaItem

    我刚刚尝试实施LocationMediaItem in my Xamarin iOS应用程序使用JSQMessagesViewController 一切都很顺利 唯一的问题是UICollectionView应该显示位置的单元格永远停留在加载
  • 从 WebBrowser 控件 C# 获取滚动值

    我试图在 WebBrowser 控件中获取网页的 Y 滚动索引 但无法访问内置滚动条的值 有任何想法吗 对于标准模式下的 IE 使用文档类型 正如你所说 scrollTop是的财产元素 而不是 HtmlDocument htmlDoc th
  • 为什么 set_symmetry_difference 无法与比较器一起使用?

    Example program include
  • C++ php 和静态库

    我创建了一个library a 其中包含 cpp 和 h 文件 其中包含很多类 嵌套类和方法 我想在 php 示例中包含这个静态库并尝试使用它 我想提一下 我是 php 新手 我已经在 test cpp 文件中测试了我的 libray a
  • 如何在标准 WPF ListView 中启用 UI 虚拟化

    我正在使用 NET 4 5 VS2012 并且我有一个 ListView 看起来像这样
  • ASP.NET MailMessage.BodyEncoding 和 MailMessage.SubjectEncoding 默认值

    很简单的问题 但我在 MSDN 上找不到答案 查找 ASP NET 将用于的默认值 MailMessage BodyEncoding and MailMessage SubjectEncoding 如果你不在代码中设置它们 Thanks F
  • 新任务中使用的依赖注入服务

    我在需要时使用依赖项注入来访问我的服务 但我现在想要创建一个并发任务 但这会由于依赖项注入对象及其生命周期而导致问题 我读过这篇文章 标题 防止多线程 Link http mehdi me ambient dbcontext in ef6
  • 您是否将信息添加到每个 .hpp/.cpp 文件的顶部? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 创建新的 C 头文件 源文件时 您会在顶部添加哪些信息 例如 您是否添加日期 您的姓名 文件描述等 您是否使用结构化格式来存储此信息 e g F
  • 如何在 DropDownList 中保留空格 - ASP.net MVC Razor 视图

    我在视图中通过以下方式绑定我的模型 问题是我的项目文本是格式化文本 单词之间有空格 如下所示 123 First 234 00 123 AnotherItem 234 00 123 Second 234 00 我想保留此项目文本中的空格 即
  • 在简单注入器中解析具有自定义参数的类

    我正在使用以下命令创建 WPF MVVM 应用程序简易注射器作为 DI 容器 现在 当我尝试从简单注入器解析视图时遇到一些问题 因为我需要在构造时将参数传递到构造函数中 而不是在将视图注册到容器时 因此这不是适用的 简单注入器将值传递到构造
  • QFileDialog::getSaveFileName 和默认的 selectedFilter

    我有 getSaveFileName 和一些过滤器 我希望当用户打开 保存 对话框时选择其中之一 Qt 文档说明如下 可以通过将 selectedFilter 设置为所需的值来选择默认过滤器 我尝试以下变体 QString selFilte

随机推荐

  • 我怎样才能在NodaTime中知道城市和它的时区之间的关系?

    目前我正在使用 NodaTime 从国家 地区获取时区 但问题是一个国家 地区是否有多个时区 我怎样才能知道该时区的城市列表 我需要知道这两个数据之间的映射 NodaTime 可以吗 正确的处理方法如下 查找每个位置的纬度和经度 如果这些是
  • 使用 MVCContrib 对 MVC 3 控制器和视图进行单元测试时将键和值添加到 RouteData

    好的 我正在使用 MVCContrib TestHelper 对我的控制器进行单元测试 效果很好 不过 像很多人一样 通过单元测试 我真正的意思是这里的集成测试 我想至少确保我的视图在给定提供的模型的情况下呈现没有错误 否则我可能会错过一整
  • SwiftUI NavigationView/Stack(如果可用)iOS 15/16

    关于从NavigationView to NavigationStack适用于 SwiftUI 4 和 iOS 16 我有 2 个应用程序在 App Store 上运行 针对 iOS 15 及更高版本 当然我正在使用NavigationVi
  • 获取 contenteditable DIV 中插入符的 HTML 位置

    我无法弄清楚如何在包含 HTML 标签的 DIV 容器中获取插入符位置 我正在使用这个 JavaScript 函数来做到这一点 function getCaretPosition if window getSelection window
  • 支持 src/ 和 test/ 的简单 ant 构建脚本?

    目前 我使用 IDE 进行所有构建和单元测试 现在我需要使用ant 我发现了一些简单的 ant build xml 脚本 但它们不支持单独的 Junit test 目录 我的项目结构如下 src com foo com bar test M
  • java中同一数组的元素比较

    我正在尝试比较同一数组的元素 这意味着我想将 0 元素与其他所有元素进行比较 将 1 元素与其他所有元素进行比较 依此类推 问题是它没有按预期工作 我所做的是我有两个从 0 到 array length 1 的 for 循环 然后我有一个
  • Netbeans 7.2 显示“无法解析标识符”,尽管构建成功

    我正在使用Netbeans IDE 7 2 with C C 插件 最新版本 1 18 1 1 和 如果我构建我的项目 一切都很好 但 IDE 会显示错误 例如 无法解析标识符 其他人也有这个错误 我该如何解决它 这是我对另一个问题的回答的
  • NEST (elasticsearch) 在多个字段中突出显示

    我已经使用 Nest 成功获得了结果和突出显示 但如果我包含两个字段来搜索突出显示 则它在构建 elasticsearch 查询时仅使用最后一个字段 例如下列 Query qry gt qry QueryString qs gt qs Qu
  • 将 SoapHeader 添加到 org.springframework.ws.WebServiceMessage

    如何将对象添加到肥皂头org springframework ws WebServiceMessage 这是我希望最终得到的结构
  • 有没有可以替代 parse_qs 来处理分号的方法?

    TL DR 哪些库 调用可用于处理包含与 parse qs 不同的分号的查询字符串 gt gt gt urlparse parse qs tagged python ruby gt gt gt tagged python 完整背景 我正在使
  • Grafana 在 url 中传递访问令牌

    我创建了一个 API 密钥来与第三方应用程序共享 grafana 面板 我想将它嵌入到 iframe 中 但它要求我登录 如何在 url 中发送访问令牌 我一直在关注 http self issued info docs draft iet
  • 使用Python OpenCV将QR码旋转到正确的位置

    我是Python的初学者 目前正在研究二维码检测和解码 我很难将检测到的二维码旋转到正确的位置 我已经用过minAreaRect 旋转我的二维码 但它不起作用 有没有解决方法或正确的方法来做到这一点 谢谢 ROI2 cv2 imread R
  • 列出 LDAP 中的根上下文

    我想列出或搜索 LDAP 树中的根上下文 我使用 Apache Directory Server 和 Java Hashtable
  • 使用未分配的局部变量“字典”

    尽管我在以下代码中分配了值 但仍收到错误 使用未分配的局部变量 字典 private static void UpdateJadProperties Uri jadUri Uri jarUri Uri notifierUri Diction
  • 如何在真实设备上调试(使用Eclipse/ADT)

    我正在尝试弄清楚如何直接在我的手机 HTC Desire 上调试应用程序 我已经安装了手机附带的 USB 驱动程序 并且使用 adb devices 时会列出手机 如何配置 eclipse ADT 在手机上启动而不是启动模拟器 虚拟设备 注
  • ASP.NET MVC 和 WCF

    我目前正在努力学习 MVC 但在我的 在某个时刻学习 列表中 我还学习了 WCF 我只是想知道 WCF 是否应该 可以在 MVC 应用程序中使用 背景是我想要一个桌面应用程序 NET 3 5 WPF 与我的 MVC 网站交互 我想知道在两者
  • 通过单个命令安装私有和公共 NPM 软件包

    我在 package json 文件中列出了一些 npm 包 有些是公共的 有些是私有的 我想通过使用在单个命令中安装两种类型的包npm install 如果 npm 注册表设置为全局 则私有包显示404 那么如何通过单个命令来实现这一点
  • jetty-maven-插件和 loadTimeWeaver

    似乎无法让我的 Spring Web 应用程序与 jetty maven 插件一起使用 我总是得到 org springframework beans factory BeanCreationException Error creating
  • 我不懂指针

    什么是指针 什么是取消引用 如果p是一个指针 有什么区别 p some value and p other value 什么是p some variable意思是 什么是NULL指针 当取消引用 NULL 指针时会发生什么 准备一叠黄色便利
  • 运行 Quartz 作业时补偿时区偏移

    我有一个独特的问题 因为我的quartz作业调度程序实现是使用quartz net代码库版本2 0 1构建的 最近发现在运行和执行作业时时区和utc偏移量被忽略 这是该版本quartz net 中的一个继承错误 更新到版本 2 1 1 目前