将日期字符串解析为某个时区(支持夏时制) [英] Parse a date string into a certain timezone (supporting daylight saving time)

查看:91
本文介绍了将日期字符串解析为某个时区(支持夏时制)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,过去几周我一直很努力,遇到了一个小问题。我认为我现在还没有完成任务:),所以我需要一些提示/帮助!



用户将在AEST中输入日期和时间。还有一个应用程序设置为默认时区(可能需要更改),当前设置为 AUS东部标准时间



因此我们有一个用户字符串在美国的服务器上没有时区和已定义的系统时区(因此本地不匹配,因此无法更改或使用)



现在我需要一种方式说使用时区X解析此用户输入的字符串,我不能只输入+10或+11作为偏移量,因为日期可能在夏令时内或外;是的,即使在相同的时区,它的确也会在+10到+11之间改变它!



当前的AEST时间也可能在DST内或外,所以我不能将UTC日期转换为当前的AEST时间,并获取 zzz字符串,并将其附加,因为对于从当前DST设置中输入的任何内容,日期都将偏离一小时。



目前,代码实际上只是这样做:

  TimeZoneInfo ConvTo = TimeZoneInfo.FindSystemTimeZoneById(ConfigurationManager.AppSettings [ DefaultTimeZone ]); 
DateTimeOffset getDate = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow,ConvTo);
string TimeZoneId = + getDate.ToString( zzz);
DateTimeOffset cvStartDate = DateTimeOffset.MinValue; DateTimeOffset.TryParse(StartDate + TimeZoneId,out cvStartDate);

然后我通过检查日期是否仍然== DateTimeOffset.MinValue来检查日期是否无效将其转换为UTC并添加到数据库中,将在显示时将其转换回AEST。但是,某些日期可能会缩短一个小时,而其他日期则是完美的(如预期的那样):)



解决这个问题的最优雅的方法是什么? b

编辑:



为帮助解释该问题,我编写了一些测试代码作为Windows测试应用程序:

  //用户输入的日期
字符串EnteredDate = 2011/01/01 10:00:00 AM;

//获取我们要使用的时区
TimeZoneInfo myTimeZone = TimeZoneInfo.FindSystemTimeZoneById( AUS东部标准时间);

//查找所选时区的时区字符串以分析用户字符串
//这是不正确的部分,我需要帮助。
DateTimeOffset getDate = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow,myTimeZone);
string TimeZoneId = + getDate.ToString( zzz);

//将字符串解析为日期对象
DateTimeOffset cvEnteredDate = DateTimeOffset.MinValue; DateTimeOffset.TryParse(EnteredDate + TimeZoneId,out cvEnteredDate);

//显示
textBox1.Text + = Parsed: + cvEnteredDate.ToString( yyyy / MM / dd HH:mm:ss zzz)+ Environment.NewLine;

//转换为UTC并显示
cvEnteredDate = cvEnteredDate.ToUniversalTime();
textBox1.Text + = UTC: + cvEnteredDate.ToString( yyyy / MM / dd HH:mm:ss zzz)+ Environment.NewLine;

//转换回AEST并显示
cvEnteredDate = TimeZoneInfo.ConvertTime(cvEnteredDate,myTimeZone);
textBox1.Text + =改回: + cvEnteredDate.ToString( yyyy / MM / dd HH:mm:ss zzz)+ Environment.NewLine;

这是什么输出?

 
已解析:2011/01/01 10:00:00 +10:00
UTC:2011/01/01 00:00:00 +00:00
改回: 2011/01/01 11:00:00 +11:00

请注意,小时数相差一,偏移量也不同。此外,如果我们仅将输入的日期更改为:

  string EnteredDate = 2011/04/20 10:00:00上午; 

我们得到:

 
已解析:2011/04/20 10:00:00 +10:00
UTC:2011/04/20 00:00:00 +00:00
改回日期:2011/04 / 20 10:00:00 +10:00

使用相同的代码,只是输入的日期不同,这是非常好的。



发生这种情况是因为当前DST设置和输入日期的DST设置不同,这就是我想要的解决方案:)



想起来像鸡肉和鸡蛋的问题。在解析字符串之前,我需要为输入的字符串提供正确的时区数据,只有在解析字符串之后才能得到它(所以这将是一个详尽的解决方案)



我需要.NET使用myTimeZone对象来解析字符串,以便它知道将其设置为什么,但是我看不到任何执行此操作的函数,它们 all 都已经解析并设置了日期时间还是datetimeoffset对象



所以我在寻找别人可能做过的优雅解决方案?我当然不是唯一注意到这一点的人吗?



EDIT2:



好吧,我已经做了一个正常工作的功能来解决我认为的问题,这是一个示例(将文本框添加到ac#Windows应用程序并使用下面的代码测试自己):

  private void Form1_Load(对象发送者,EventArgs e)
{
TimeZoneInfo myTimeZone = TimeZoneInfo.FindSystemTimeZoneById( AUS东部标准时间);

DateTimeOffset get1Date = ReadStringWithTimeZone( 2011/01/01 10:00:00 AM,myTimeZone);
textBox1.Text + = Read1: + get1Date.ToString( yyyy / MM / dd HH:mm:ss zzz)+ Environment.NewLine;
get1Date = get1Date.ToUniversalTime();
textBox1.Text + = Read1-UTC: + get1Date.ToString( yyyy / MM / dd HH:mm:ss zzz)+ Environment.NewLine;
get1Date = TimeZoneInfo.ConvertTime(get1Date,myTimeZone);
textBox1.Text + =改回: + get1Date.ToString( yyyy / MM / dd HH:mm:ss zzz)+ Environment.NewLine + Environment.NewLine;

DateTimeOffset get2Date = ReadStringWithTimeZone( 2011/04/20 10:00:00 AM,myTimeZone);
textBox1.Text + = Read2: + get2Date.ToString( yyyy / MM / dd HH:mm:ss zzz)+ Environment.NewLine;
get2Date = get2Date.ToUniversalTime();
textBox1.Text + = Read2-UTC: + get2Date.ToString( yyyy / MM / dd HH:mm:ss zzz)+ Environment.NewLine;
get2Date = TimeZoneInfo.ConvertTime(get2Date,myTimeZone);
textBox1.Text + =改回: + get2Date.ToString( yyyy / MM / dd HH:mm:ss zzz)+ Environment.NewLine + Environment.NewLine;
}

public DateTimeOffset ReadStringWithTimeZone(string EnteredDate,TimeZoneInfo tzi)
{
DateTimeOffset cvUTCToTZI = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow,tzi);
DateTimeOffset cvParsedDate = DateTimeOffset.MinValue; DateTimeOffset.TryParse(EnteredDate + + cvUTCToTZI.ToString( zzz),cvParsedDate之外);
if(tzi.SupportsDaylightSavingTime)
{
TimeSpan getDiff = tzi.GetUtcOffset(cvParsedDate);
字符串MakeFinalOffset =(getDiff.Hours< 0?-: +)+(getDiff.Hours> 9?: 0)+ getDiff.Hours +: +(getDiff 。分钟> 9?: 0)+ getDiff.Minutes;
textBox1.Text + = Diff: + MakeFinalOffset + Environment.NewLine;
DateTimeOffset.TryParse(EnteredDate + + MakeFinalOffset,cvParsedDate输出);
返回cvParsedDate;
}
其他
{
return cvParsedDate;
}
}

输出:

 
差异:+11:00
Read1:2011/01/01 10:00:00 +11:00
Read1-UTC:2010 / 12/31 23:00:00 +00:00
改回:2011/01/01 10:00:00 +11:00

区别:+10:00
Read2:2011/04/20 10:00:00 +10:00
Read2-UTC:2011/04/20 00:00:00 +00:00
Changed Back:2011/04 / 20 10:00:00 +10:00

只有当用户输入的日期正确时,才可能出现问题。在DST的一个小时内进行更改,由于它只是读取当前偏移量并使用该偏移量,因此可能仍需要一个小时的时间,然后检查其是否应为夏时制,以及是否在该处偏移不正确。但是它比我现在要好得多。



有人可以帮我清理此功能吗?这是我需要的最佳路线吗?

解决方案

这里有一个针对预定义格式的简单解决方案,它也可以是动态的。我个人使用它与javascript交谈:

  public DateTimeOffset ParseDateExactForTimeZone(string dateTime,TimeZoneInfo时区)
{
var parsedDateLocal = DateTimeOffset.ParseExact(dateTime, yyyy-MM-dd HH:mm:ss,CultureInfo.InvariantCulture);
var tzOffset = timezone.GetUtcOffset(parsedDateLocal.DateTime);
var parsedDateTimeZone = new DateTimeOffset(parsedDateLocal.DateTime,tzOffset);
return parsedDateTimeZone;
}


Ok i've been working very hard the last few weeks and i've come across a small problem. I don't think my mind is quite up to the task right now :) so i need some tips/help! it's likely very simple but my head isn't clicking yet.

Users will enter a date and time in AEST. There is also a application set "default" timezone (as it might need to change), currently its set to "AUS Eastern Standard Time"

So we have a user string with no time zone and a defined system time zone on a server in the USA (So local doesn't match and it can't be changed or used)

Now what i need is a way to say "parse this user entered string using the timezone X" i can't just enter +10 or +11 as the offset as the dates could be in or out of daylight savings; which yes does change it between +10 and +11 even for the same timezone!

The current AEST time might also be in or out of DST so i can't just convert a UTC date to the current AEST time and get the "zzz" string and attach it either as dates will be off by an hour for anything entered out of the current DST setting.

For now the code actually does just that:

TimeZoneInfo ConvTo = TimeZoneInfo.FindSystemTimeZoneById(ConfigurationManager.AppSettings["DefaultTimeZone"]);
DateTimeOffset getDate = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, ConvTo);
string TimeZoneId = " " + getDate.ToString("zzz");
DateTimeOffset cvStartDate = DateTimeOffset.MinValue; DateTimeOffset.TryParse(StartDate + TimeZoneId, out cvStartDate);

Then i check if the date isn't valid by checking if it still == DateTimeOffset.MinValue or convert it to UTC and add to the database, it will the be converted back to AEST when displayed. However some dates are off by an hour and others are perfect (as expected) :)

What is the most elegant way to solve this?

EDIT:

To help explain the problem, i wrote some test code as a windows test application:

// User entered date
string EnteredDate = "2011/01/01 10:00:00 AM";

// Get the timezone we want to use
TimeZoneInfo myTimeZone = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");

// Find the timezone string of the selected timezone to parse the user string
// This is the part that is incorrect and what i need help with.
DateTimeOffset getDate = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, myTimeZone);
string TimeZoneId = " " + getDate.ToString("zzz");

// Parse the string into the date object
DateTimeOffset cvEnteredDate = DateTimeOffset.MinValue; DateTimeOffset.TryParse(EnteredDate + TimeZoneId, out cvEnteredDate);

// Display
textBox1.Text += "Parsed: " + cvEnteredDate.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine;

// Convert to UTC and display
cvEnteredDate = cvEnteredDate.ToUniversalTime();
textBox1.Text += "UTC: " + cvEnteredDate.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine;

// Convert back to AEST and display
cvEnteredDate = TimeZoneInfo.ConvertTime(cvEnteredDate, myTimeZone);
textBox1.Text += "Changed Back: " + cvEnteredDate.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine;

Whats the output of this?

Parsed: 2011/01/01 10:00:00 +10:00
UTC: 2011/01/01 00:00:00 +00:00
Changed Back: 2011/01/01 11:00:00 +11:00

Please note the hour is off by one and the offset is different. Additionally, what if we JUST change the date entered to:

string EnteredDate = "2011/04/20 10:00:00 AM";

we get:

Parsed: 2011/04/20 10:00:00 +10:00
UTC: 2011/04/20 00:00:00 +00:00
Changed Back: 2011/04/20 10:00:00 +10:00

Which is perfectly good and fine, using the same code just a different entered date.

This happens because the current DST setting and the DST setting of the entered date are different, this is what i want a solution for :)

Think of it like the chicken and egg problem. I need the correct timezone data for the entered string before i parse it which i can only get after i've parsed the string (so will be an elaborate solution)

Or i need .NET to parse the string using the myTimeZone object so it knows what to set it to itself, but i can't see any functions that do this, they all take a already parsed and set datetime or datetimeoffset object

So i'm looking for elegant solutions others might have done? I certainly can't be the only one who has noticed this?

EDIT2:

Ok i've made a 'working' function that solves the problem i think, here is an example (add a textbox to a c# windows app and use the code below to test yourself):

private void Form1_Load(object sender, EventArgs e)
{
    TimeZoneInfo myTimeZone = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");

    DateTimeOffset get1Date = ReadStringWithTimeZone("2011/01/01 10:00:00 AM", myTimeZone);
    textBox1.Text += "Read1: " + get1Date.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine;
    get1Date = get1Date.ToUniversalTime();
    textBox1.Text += "Read1 - UTC: " + get1Date.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine;
    get1Date = TimeZoneInfo.ConvertTime(get1Date, myTimeZone);
    textBox1.Text += "Changed Back: " + get1Date.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine + Environment.NewLine;

    DateTimeOffset get2Date = ReadStringWithTimeZone("2011/04/20 10:00:00 AM", myTimeZone);
    textBox1.Text += "Read2: " + get2Date.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine;
    get2Date = get2Date.ToUniversalTime();
    textBox1.Text += "Read2 - UTC: " + get2Date.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine;
    get2Date = TimeZoneInfo.ConvertTime(get2Date, myTimeZone);
    textBox1.Text += "Changed Back: " + get2Date.ToString("yyyy/MM/dd HH:mm:ss zzz") + Environment.NewLine + Environment.NewLine;
}

public DateTimeOffset ReadStringWithTimeZone(string EnteredDate, TimeZoneInfo tzi)
{
    DateTimeOffset cvUTCToTZI = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, tzi);
    DateTimeOffset cvParsedDate = DateTimeOffset.MinValue; DateTimeOffset.TryParse(EnteredDate + " " + cvUTCToTZI.ToString("zzz"), out cvParsedDate);
    if (tzi.SupportsDaylightSavingTime)
    {
        TimeSpan getDiff = tzi.GetUtcOffset(cvParsedDate);
        string MakeFinalOffset = (getDiff.Hours < 0 ? "-" : "+") + (getDiff.Hours > 9 ? "" : "0") + getDiff.Hours + ":" + (getDiff.Minutes > 9 ? "" : "0") + getDiff.Minutes;
        textBox1.Text += "Diff: " + MakeFinalOffset + Environment.NewLine;
        DateTimeOffset.TryParse(EnteredDate + " " + MakeFinalOffset, out cvParsedDate);
        return cvParsedDate;
    }
    else
    {
        return cvParsedDate;
    }
}

And the output:

Diff: +11:00
Read1: 2011/01/01 10:00:00 +11:00
Read1 - UTC: 2010/12/31 23:00:00 +00:00
Changed Back: 2011/01/01 10:00:00 +11:00

Diff: +10:00
Read2: 2011/04/20 10:00:00 +10:00
Read2 - UTC: 2011/04/20 00:00:00 +00:00
Changed Back: 2011/04/20 10:00:00 +10:00

Only thing is there might be a problem if the user entered date is right on the change over hour of DST it still might be an hour off as it's just reading the current offset and using that, then checking if its supposed to be daylight savings or not, and if its out there it would read incorrectly. However it's miles better than what i have now.

Can anyone maybe help me with cleaning up this function? Is this the best route go down for what i need? ideas?

解决方案

Heres a simple solution for a predefined format, this can be dynamic as well. I personally use this for talking with javascript:

public DateTimeOffset ParseDateExactForTimeZone(string dateTime, TimeZoneInfo timezone)
{
    var parsedDateLocal = DateTimeOffset.ParseExact(dateTime, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
    var tzOffset = timezone.GetUtcOffset(parsedDateLocal.DateTime);
    var parsedDateTimeZone = new DateTimeOffset(parsedDateLocal.DateTime, tzOffset);
    return parsedDateTimeZone;
}

这篇关于将日期字符串解析为某个时区(支持夏时制)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆