【问题标题】:Determine if current time between multiple time spans确定多个时间跨度之间的当前时间
【发布时间】:2012-07-10 14:46:47
【问题描述】:

我无法确定任何特定时间处于哪个交易时段。

有四个可能的会话,显示在这张来自 ForexFactory.com 的图片中

我有这个方法,我需要检查当前时间是否在指定的交易时段内。

public bool IsTradingSession(TradingSession tradingSession, DateTime currentTime)
{
    //currentTime is in local time.


    //Regular session is 5PM - next day 5PM, this is the session in the picture.
    //Irregular sessions also occur for example late open (3AM - same day 5PM)  or early close (5PM - next day 11AM)
    DateTime sessionStart = Exchange.ToLocalTime(Exchange.CurrentSessionOpen);
    DateTime sessionEnd = Exchange.ToLocalTime(Exchange.CurrentSessionClose);

    if(tradingSession == TradingSession.Sydney)
        return ....... ? true : false;
    if(tradingSession == TradingSession.Tokyo)
        return ....... ? true : false;        
    if(tradingSession == TradingSession.London)
        return ....... ? true : false;
    if (tradingSession == TradingSession.NewYork)
        return ....... ? true : false;

    return false;
}

用途:

    bool isSydneySession = IsTradingSession(TradingSession.Sydney, CurrentTime);
    bool isTokyoSession = IsTradingSession(TradingSession.Tokyo, CurrentTime);
    bool isLondonSession = IsTradingSession(TradingSession.London, CurrentTime);
    bool isNewYorkSession = IsTradingSession(TradingSession.NewYork, CurrentTime);

谢谢

【问题讨论】:

  • .NET DateTime 是出了名的难以正确使用,尤其是在不同时区的情况下。如果您能影响是否使用标准 DateTime 的决定,请考虑查看 code.google.com/p/noda-time
  • 如果currentTime 始终处于一致的时区,则不需要UTC;为简单起见,坚持当地时间不会有什么坏处。
  • @Kirk Broadhurst 是的,这是我在评论中提到的 dthorpe 回答的问题
  • @user1267778 根据交易时段是一天还是两天,您需要自定义功能。检查我的更新答案
  • 您在下面有很好的答案。但是,如果您想了解更多关于时间编程的基础知识,这可能会有所帮助 - blogs.windwardreports.com/davidt/2009/11/…

标签: c# .net datetime time


【解决方案1】:

您可以使用 > &

查看相关问题:Check if datetime instance falls in between other two datetime objects

为了避免多个 if 语句,您还可以创建一个包含开始和结束时间的 TradingSession 对象,并定义一个属性/函数来检查是否在会话中。当我有大开关或 if 阻塞时,通常表明错过了 OO 机会:)

TradingSession sydneySession = new TradingSession 
{
    StartTimeUtc = ...;
    EndTimeUtc = ...;
}

然后交易会话对象可以有一个属性 IsInSession。

public bool IsInSession
{
    get {
        return DateTime.UTCNow >= StartTimeUtc && DateTime.UTCNow <= EndTimeUtc;
    }
}

这使用 UTC 时间来消除时区问题。

【讨论】:

    【解决方案2】:

    您需要将本地时间标准化为 UTC。然后,您可以比较不同地区的时间。

    对于每个交易时段,您需要知道交易时段的开始和结束时间(UTC)。

    您需要以 UTC 表示的当前时间。以DateTime.UtcNow 为例。

    然后您可以对每个交易时段窗口进行范围比较:

    if(tradingSession == TradingSession.Sydney)
            return currentTimeUtc >= sydneyStartTimeUtc && currentTimeUtc <= sydneyEndTimeUtc;
    

    等等……

    如果您尝试验证交易时间对于特定交易时段的交易是否有效,则可以正常工作。

    但是,如果您想根据交易时间确定交易属于哪个交易时段,有时您会得到多个答案,因为交易时段重叠。多个交易时段可能在给定时间内有效。

    【讨论】:

    • 我还没有解决这个问题。请忽略图中蓝色方框内的会议时间,这可能会造成一些混乱。方法中的所有时间都是当地时间 ei CurrentTime、sessionStart、sessionEnd 等都是当地时间(我编辑了我的方法以反映这一点)。只要在被比较的所有时间都保持一致,就看不出在哪个时区进行比较有多重要。我想我仍然缺少一些东西。
    • 也许我对如何根据整个会话的开始和结束时间(下午 5 点 - 第二天下午 5 点)定义每个单独会话(sydneyStartTime、sydneyEndTime、tokyoStartTime、tokyoEndTime 等)的实际时间感到困惑) 这可能是也可能不是 IRREGULAR(例如,凌晨 3 点至同一天下午 5 点开放将跳过整个悉尼会议和东京会议的一部分,仅在伦敦会议开始时开放。
    • 你需要更好地定义你的问题。
    【解决方案3】:

    我建议为每个交易时段编写一个简单的函数,它接受一个 DateTime 并返回一个布尔值,指示它在那个时间是否开放。

    var sydneyOpen = new TimeSpan(17, 0, 0);
    var sydneyClose = new TimeSpan(2, 0, 0);
    Func<DateTime, bool> isOpenInSydney = d => 
        (d.TimeOfDay > sydneyOpen || d.TimeOfDay < sydneyClose);
    
    // same for other markets, write a function to check against two times
    

    然后将它们放入像这样的Dictionary&lt;TradingSession, Func&gt; 以进行通用检索...

    var marketHours = new Dictionary<TradingSession, Func<DateTime, bool>>();
    marketHours.Add(TradingSession.Sydney, isOpenInSydney);
    // add other markets...
    

    然后您现有的方法只需为给定的TradingSession 选择适当的函数并应用它

    public bool IsTradingSession(TradingSession tradingSession, DateTime currentTime)
    {
        var functionForSession = marketHours[tradingSession];
        return functionForSession(currentTime);
    }
    

    只要您的应用程序仅在单个时区运行,我认为您在这里不需要 UTC 时间,但夏令时可能会导致问题。


    解决两天而不是一天的交易时段问题的一种好方法是编写一个帮助程序,它可以精确考虑它是否是“跨日”交易时段并应用不同的规则你:

    private bool IsBetween(DateTime now, TimeSpan open, TimeSpan close)
    {
        var nowTime = now.TimeOfDay;
        return (open < close
            // if open is before close, then now must be between them
            ? (nowTime > open && nowTime < close)
            // otherwise now must be *either* after open or before close
            : (nowTime > open || nowTime < close));
    }
    

    然后

    var sydneyOpen = new TimeSpan(17, 0, 0);
    var sydneyClose = new TimeSpan(2, 0, 0);
    Func<DateTime, bool> isOpenInSydney = d => IsBetween(d, sydneyOpen, sydneyClose);
    

    【讨论】:

    • 对 sydneyStart、sydneyEnd、tokyoStart 等使用时间跨度对象是我最初的开始方式。问题在于 d.TimeOfDay(比如说早上 8 点)在 sydneyClose = new TimeSpan(2,0,0) 之前和之后
    • 为什么不呢?如果 currentTime = new DateTime(2012, 7, 10, 8, 00, 00) 那么 currentTime.TimeOfDay (8AM) 在 7/10/2012 2AM sydneyClose 之后和 2012/7/11 2AM sydneyClose 之前,不是吗?
    • @user1267778 对于任何给定时间,它是在上一次关闭之后和下一次关闭之前。但是你应该只考虑当天的开盘和收盘时间,否则你会迷惑自己。这就是TimeOfDay 所做的 - 将您限制在当前的 24 小时内。让事情变得更简单!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多