判断某个时区的时间是否在一个范围内
Determine if the time an a certain timezone is within a range
我公司的支持人员在美国中部标准时间早上 7 点到晚上 7 点有空,我们试图通过显示启动聊天的按钮或显示他们不可用的消息来在我们的网站上反映这一点。支持人员位于中部时间,但托管我们网站的服务器可能位于任何时区。 (我远程工作,当我在我的机器上本地 运行 项目时,例如在东部时间)
现在有一个错误,表明您在美国中部标准时间下午 6 点不在时间范围内,这早了一个小时。这似乎是因为我在 CST 中的时间范围实际上跨越 UTC 时间的 2 天(下午 1 点到第二天凌晨 1 点),并且我的时间基于 UTC 日期。我知道这是导致问题的原因,但我不确定解决此问题的最佳方法。
这是代码,从 returns 布尔值的函数转换为控制台应用程序以注销 eh 值。
查看下面的代码,或在此处使用:https://dotnetfiddle.net/Hzhv8n
//=================================================================================================
//Get hours & days of operation
//These normally come from a config file, but hardcoding them here for demo
int availableChatStartHour = 13; //7am CST in UTC time
int availableChatDuration = 12; //12 hours from 7am CST is 7pm CST
string[] availableDaysForChat = "monday,tuesday,wednesday,thursday,friday".ToUpper().Split(',');
//=================================================================================================
//The current timezone-agnostic time.
var now = DateTime.UtcNow;
//Convert times to a date object
//-------------------------------------------------
//I THINK THIS IS WHERE MY BUG IS
var startTime = new DateTime(now.Year, now.Month, now.Day, availableChatStartHour, 0, 0, DateTimeKind.Utc);
//-------------------------------------------------
var endTime = startTime.AddHours(availableChatDuration);
//Company HQ is located in the central time zone
//The central time zone can experience daylight saving time.
//We need to determine if DST is currently active or not in CST
var cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
var cstTime = TimeZoneInfo.ConvertTimeFromUtc(now, cstZone);
var isDstActive = cstZone.IsDaylightSavingTime(cstTime);
//If DST is active, then we need to subtract an hour from the start and end times.
if (isDstActive)
{
startTime = startTime.AddHours(-1);
endTime = endTime.AddHours(-1);
}
//Determine if the day of the week (in CST time) is available for chat
var isDayAvilable = availableDaysForChat.Contains(cstTime.DayOfWeek.ToString().ToUpper());
//Make sure the time of day is within the acceptable range
var isAfterStartTime = now > startTime;
var isBeforeEndTime = now < endTime;
//Now take everything into account and see if the chat is available
//return isDayAvilable && isAfterStartTime && isBeforeEndTime;
Console.WriteLine("NOW: "+ now);
Console.WriteLine("START: "+ startTime);
Console.WriteLine("END: "+ endTime);
Console.WriteLine("-------------------------------------");
Console.WriteLine("Day Available: "+isDayAvilable);
Console.WriteLine("Is After Start Time: "+ isAfterStartTime);
Console.WriteLine("Is Before End Time: "+ isBeforeEndTime);
Console.WriteLine("-------------------------------------");
Console.WriteLine("FINAL RESULT: "+ (isDayAvilable && isAfterStartTime && isBeforeEndTime));
关于如何使这项工作正常进行的任何想法?
您所做的 远远超过您需要做的。我个人会使用 Noda Time project, but all of this can be done fairly easily with the BCL, using TimeZoneInfo.ConvertTime
:
var zone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
var centralTime = TimeZoneInfo.ConvertTime(DateTime.UtcNow, zone);
if (centralTime.Hour >= 7 && centralTime.Hour < 21 &&
centralTime.DayOfWeek >= DayOfWeek.Monday &&
centralTime.DayOfWeek <= DayOfWeek.Friday)
{
// Yes, you have support staff
}
else
{
// Nope, let the answerphone handle it
}
我公司的支持人员在美国中部标准时间早上 7 点到晚上 7 点有空,我们试图通过显示启动聊天的按钮或显示他们不可用的消息来在我们的网站上反映这一点。支持人员位于中部时间,但托管我们网站的服务器可能位于任何时区。 (我远程工作,当我在我的机器上本地 运行 项目时,例如在东部时间)
现在有一个错误,表明您在美国中部标准时间下午 6 点不在时间范围内,这早了一个小时。这似乎是因为我在 CST 中的时间范围实际上跨越 UTC 时间的 2 天(下午 1 点到第二天凌晨 1 点),并且我的时间基于 UTC 日期。我知道这是导致问题的原因,但我不确定解决此问题的最佳方法。
这是代码,从 returns 布尔值的函数转换为控制台应用程序以注销 eh 值。
查看下面的代码,或在此处使用:https://dotnetfiddle.net/Hzhv8n
//=================================================================================================
//Get hours & days of operation
//These normally come from a config file, but hardcoding them here for demo
int availableChatStartHour = 13; //7am CST in UTC time
int availableChatDuration = 12; //12 hours from 7am CST is 7pm CST
string[] availableDaysForChat = "monday,tuesday,wednesday,thursday,friday".ToUpper().Split(',');
//=================================================================================================
//The current timezone-agnostic time.
var now = DateTime.UtcNow;
//Convert times to a date object
//-------------------------------------------------
//I THINK THIS IS WHERE MY BUG IS
var startTime = new DateTime(now.Year, now.Month, now.Day, availableChatStartHour, 0, 0, DateTimeKind.Utc);
//-------------------------------------------------
var endTime = startTime.AddHours(availableChatDuration);
//Company HQ is located in the central time zone
//The central time zone can experience daylight saving time.
//We need to determine if DST is currently active or not in CST
var cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
var cstTime = TimeZoneInfo.ConvertTimeFromUtc(now, cstZone);
var isDstActive = cstZone.IsDaylightSavingTime(cstTime);
//If DST is active, then we need to subtract an hour from the start and end times.
if (isDstActive)
{
startTime = startTime.AddHours(-1);
endTime = endTime.AddHours(-1);
}
//Determine if the day of the week (in CST time) is available for chat
var isDayAvilable = availableDaysForChat.Contains(cstTime.DayOfWeek.ToString().ToUpper());
//Make sure the time of day is within the acceptable range
var isAfterStartTime = now > startTime;
var isBeforeEndTime = now < endTime;
//Now take everything into account and see if the chat is available
//return isDayAvilable && isAfterStartTime && isBeforeEndTime;
Console.WriteLine("NOW: "+ now);
Console.WriteLine("START: "+ startTime);
Console.WriteLine("END: "+ endTime);
Console.WriteLine("-------------------------------------");
Console.WriteLine("Day Available: "+isDayAvilable);
Console.WriteLine("Is After Start Time: "+ isAfterStartTime);
Console.WriteLine("Is Before End Time: "+ isBeforeEndTime);
Console.WriteLine("-------------------------------------");
Console.WriteLine("FINAL RESULT: "+ (isDayAvilable && isAfterStartTime && isBeforeEndTime));
关于如何使这项工作正常进行的任何想法?
您所做的 远远超过您需要做的。我个人会使用 Noda Time project, but all of this can be done fairly easily with the BCL, using TimeZoneInfo.ConvertTime
:
var zone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
var centralTime = TimeZoneInfo.ConvertTime(DateTime.UtcNow, zone);
if (centralTime.Hour >= 7 && centralTime.Hour < 21 &&
centralTime.DayOfWeek >= DayOfWeek.Monday &&
centralTime.DayOfWeek <= DayOfWeek.Friday)
{
// Yes, you have support staff
}
else
{
// Nope, let the answerphone handle it
}