Given the 11:00 PM
, and knowing that the server is running using UTC time, I need to take that time parse it into a DateTimeOffset from a specific TimeZone.
For example if the docker container's time running the server is 2:00 AM 6/3/2022, I need to be able to check if current date time now in 'Eastern Standard Time' zone, is past 6/2/2022 11:00 PM
or before.
To get localized DateTime now I have the following code which works as expected:
TimeZoneInfo tzInfo = TimeZoneInfo.FindSystemTimeZoneById(zoneId);
DateTime nowLocalTime = TimeZoneInfo.ConvertTime(DateTime.Now, tzInfo);
DateTimeOffset targetDateTimeOffset =
new DateTimeOffset(nowLocalTime,
tzInfo.GetUtcOffset
(
DateTime.SpecifyKind(nowLocalTime, DateTimeKind.Local)
));
I thought I had it figured out for parsing the time into DateTime and then getting the specific DateTimeOffset object, until it hit past midnight on the server. Since the server's time is now 12:01 AM 6/3/2022
when I run the following code:
string timeOfDay = "11:00 AM";
TimeZoneInfo tzInfo = TimeZoneInfo.FindSystemTimeZoneById(zoneId);
DateTime.TryParse(timeOfDay, out DateTime dateTime);
DateTimeOffset targetDateTimeOffset =
new DateTimeOffset
(
dateTime,
tzInfo.GetUtcOffset
(
DateTime.SpecifyKind(dateTime,
DateTimeKind.Local)
)
);
This now returns 6/3/2022 11:00PM
. This makes sense but I need to get DateTimeOffset parsed into the specified TimeZone. Because right now in 'Eastern Standard Time' zone it is 6/2/2022 not 6/3/2022. So basically I need to take 11:00 PM
parse it into DateTimeOffset
of the provided TimeZone, is that possible?
The .net DateTime
type was designed before the age of cloud computing. Where you only had to worry about the machine's .Local
time or .Utc
. IMHO DateTimeKind.Unspecified
should be marked [Obsolete]
and any API behaviour which relies on it should instead throw an exception.
TimeZoneInfo.ConvertTime(DateTime, TimeZoneInfo)
is a particularly strange function. If you pass a DateTimeKind.Unspecified
, or a TimeZoneInfo
other than TimeZoneInfo.Local
or TimeZoneInfo.Utc
, the result is essentially unusable.
IMHO you're better off pushing the problem of parsing and displaying date / time values to the client. Force the client to parse any date time strings in their local timezone. Then either use UTC everywhere, or use DateTimeOffset
to store the timezone explicitly.
It's easy enough to get the current time in a specific timezone;
TimeZoneInfo tzInfo = TimeZoneInfo.FindSystemTimeZoneById(zoneId);
DateTimeOffset tzLocalTime = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, tzInfo);
Unfortunately while you can parse a string and .AssumeLocal
or .AssumeUniversal
, anything else is barely supported or documented. While you can provide a CultureInfo
for parsing non-gregorian calendars, there's no DateTimeOffset.Parse
which takes a default TimeZoneInfo
parameter. The closest I've found is to check if the string contains an offset, based on this question .
static DateTimeOffset ParseAsDateTimeOffset(string s, TimeZoneInfo defaultTimeZone, CultureInfo culture = null)
{
if (Regex.IsMatch(s, @"(Z|[+-]\d{2}:\d{2})$"))
return DateTimeOffset.Parse(s, culture ?? CultureInfo.InvariantCulture);
var dt = DateTime.Parse(s, culture ?? CultureInfo.InvariantCulture);
return new DateTimeOffset(dt, defaultTimeZone.GetUtcOffset(dt));
}
While this works for most of the year, I'm not certain if it works properly for time values around DST adjustments. But without an explicit offset, those values are going to be wrong anyway.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.