Самое простое решение: сначала проанализируйте строку в локальном DateTime, используйте любой метод синтаксического анализа, затем вызовите
о, я работал очень усердно в последние несколько недель, и я столкнулся с небольшой проблемой. Я не думаю, что мой разум сейчас вполне готов к этой задаче :), поэтому мне нужны некоторые советы / помощь! это, вероятно, очень просто, но моя голова еще не щелкает.
Пользователи будут вводить дату и время в AEST. Существует также приложение, устанавливающее часовой пояс по умолчанию (так как его может потребоваться изменить), в настоящее время оно установлено на «AUS Eastern Standard Time»
Таким образом, у нас есть пользовательская строка без часового пояса и определенного системного часового пояса на сервере в США (локальный не совпадает, и его нельзя изменить или использовать).
Теперь мне нужен способ сказать: "проанализировать введенную пользователем строку с использованием часового пояса X", я не могу просто ввести +10 или +11 в качестве смещения, поскольку даты могут быть в летнее время или вне его; что да, меняет его между +10 и +11 даже для одного и того же часового пояса!
Текущее время AEST также может быть в или из летнего времени, поэтому я не могу просто преобразовать дату UTC в текущее время AEST, получить строку «zzz» и присоединить ее, так как даты будут отключены на час для любого введенного значения. текущей настройки летнего времени.
На данный момент код фактически делает именно это:
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 при отображении. Однако некоторые даты отстают на час, а другие идеальны (как и ожидалось) :)
Какой самый элегантный способ решить эту проблему?
РЕДАКТИРОВАТЬ:
Чтобы помочь объяснить проблему, я написал тестовый код в качестве тестового приложения Windows:
// 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;
Каков выход этого?
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
Обратите внимание, что время выключено на один, а смещение отличается. Кроме того, что если мы просто изменим введенную дату на:
string EnteredDate = "2011/04/20 10:00:00 AM";
мы получили:
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
Что очень хорошо и хорошо, используя один и тот же код, просто другую введенную дату.
Это происходит потому, что текущие настройки DST и настройки DST для введенной даты отличаются, это то, для чего я хочу найти решение :)
Думайте об этом как о проблеме курицы и яйца. Мне нужны правильные данные часового пояса для введенной строки, прежде чем я ее проанализирую, которую я могу получить только после того, как я проанализировал строку (поэтому это будет сложное решение)
Или мне нужен .NET для разбора строки с использованием объекта myTimeZone, чтобы он знал, что для себя установить, но я не вижу никаких функций, которые делают это, онивсе взять уже проанализированный и установить объект datetime или datetimeoffset
Так что я ищу элегантные решения, которые могли бы сделать другие? Я, конечно, не могу быть единственным, кто это заметил?
EDIT2:
Хорошо, я сделал «рабочую» функцию, которая решает проблему, я думаю, вот пример (добавьте текстовое поле в приложение c # windows и используйте код ниже, чтобы проверить себя):
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;
}
}
И вывод:
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
Единственное, что может быть проблемой, если введенная пользователем дата находится на правильном изменении в течение часа по летнему времени, она все еще может быть на часе отключена, поскольку она просто читает текущее смещение и использует его, а затем проверяет, должно ли оно быть при переходе на летнее время или нет, и если бы он там был, он читал бы неправильно. Однако это намного лучше, чем у меня сейчас.
Может кто-нибудь может помочь мне с очисткой этой функции? Это лучший маршрут для того, что мне нужно? идеи?