Как да конвертирате отместване на низ във времеви интервал в c#

Опитвам се да конвертирам времето за преобразуване в часовата зона на потребителя, но нямам низа за часова зона на Windows, като например „Тихоокеанско стандартно време“. Всичко, което имам, е отместване на низ като "-07:00". Изглежда, че трябва да създам времеви интервал. Единственият начин ли е да анализирате този низ ръчно?. Изглежда, че трябва да има начин за преобразуване на време с помощта на отместване на низ, но може би пропускам нещо.

Имам това, но изисква часовата зона. Опитвам се да го модифицирам, за да използва отместването вместо това, но можете да видите времевия интервал, който е създаден за преобразуването, и трябва да получа своето отместване спрямо времевия интервал.

static void Main(string[] args)
{
    var currentTimeInPacificTime = ConvertUtcTimeToTimeZone(DateTime.UtcNow, "Pacific Standard Time");
    //TimeSpan ts = new TimeSpan("-07:00");
    Console.ReadKey();
}

static DateTimeOffset ConvertUtcTimeToTimeZone(DateTime dateTime, string toTimeZoneDesc)
{
    if (dateTime.Kind != DateTimeKind.Utc) throw new Exception("dateTime needs to have Kind property set to Utc");
    TimeSpan toUtcOffset = TimeZoneInfo.FindSystemTimeZoneById(toTimeZoneDesc).GetUtcOffset(dateTime);
    var convertedTime = DateTime.SpecifyKind(dateTime.Add(toUtcOffset), DateTimeKind.Unspecified);
    return new DateTimeOffset(convertedTime, toUtcOffset);
}

person KingOfHypocrites    schedule 17.08.2013    source източник


Отговори (4)


Можете просто да използвате метода TimeSpan.Parse:

TimeSpan ts = TimeSpan.Parse("-07:00");
Console.WriteLine(ts);   // -07:00:00

Внимавайте да премахнете водещ +, тъй като TimeSpan.Parse ще се провали тук. +01:00 е неправилно, но 01:00 работи.

Или ако искате да сте малко по-безопасни, опитайте метода TimeSpan.TryParse :

TimeSpan ts;
if (TimeSpan.TryParse("-07:00", out ts))
    Console.WriteLine(ts);   // -07:00:00

Но разбира се, ако всичко, което искате да направите, е да конвертирате UTC дата/час в местна дата/час, можете просто да направите това:

DateTime localDateTime = utcDateTime.ToLocalTime();

Или да го преобразувате във всяка часова зона:

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(toTimeZoneDesc);
DateTime localDateTime = TimeZoneInfo.ConvertTime(utcDateTime, tzi);
person p.s.w.g    schedule 17.08.2013
comment
Благодаря! Толкова просто. Не се сетих да търся метод за анализ. - person KingOfHypocrites; 18.08.2013
comment
TimeSpan.Parse е правилен за тази част от въпроса, но внимавайте за .ToLocalTime(), защото това ще бъде в часовата зона на компютъра, на който работи - който вероятно ще бъде сървър в друга часова зона. Последният кодов блок е правилен, но той каза, че няма идентификатор на часова зона за въвеждане. - person Matt Johnson-Pint; 18.08.2013
comment
Това не работи, ако отместващият ви низ съдържа знака +. Това първо трябва да се премахне. - person PaulG; 20.03.2014

За по-сложни/нестандартни формати можете също да използвате TimeSpan.ParseExact(String, String, IFormatProvider), където вторият низ е Низ с персонализиран формат на TimeSpan.

Информацията за API е достъпна на msdn.microsoft.com и е свързана по-горе.linked.

person Andrew Ring    schedule 17.08.2013

Опитвам се да конвертирам времето за преобразуване в часовата зона на потребителя, но нямам низа за часова зона на Windows, като например „Тихоокеанско стандартно време“. Всичко, което имам, е отместване на низ като "-07:00".

Тогава нямате това, от което се нуждаете, за да направите правилното преобразуване. Прочетете „Часова зона != Отместване“ в уикито за маркери за часови зони.

Важно е да разберете, че стойността "Pacific Standard Time" е .Id за обекта TimeZoneInfo, който се използва за Тихоокеанско време в САЩ. Покрива както тихоокеанското стандартно време (UTC-8) и тихоокеанското лятно часово време (UTC-7).

Всичко, което имам, е отместване на низ като "-07:00". Изглежда, че трябва да създам времеви интервал.

Сега имате това, което обикновено се нарича проблем XY. Не трябва да имате нужда да работите с отместването само по себе си.

Във вашия код има извикване на dateTime.Add(toUtcOffset). Когато правите преобразуване на часови зони, това е мирис на код, че го правите погрешно. Никога не трябва да добавяте или изваждате ръчно време само за да манипулирате часовите зони. Това трябва да бъде запазено за действителна промяна на момента във времето, за който говорите.

Това, което трябва да направите, е да съберете идентификатор на реална часова зона от вашия потребител. Или "Pacific Standard Time" за използване с TimeZoneInfo, или "America/Los_Angeles" за използване с изпълнение на TZDB като Noda Time.

Ако преобразуванията на часови зони не са важни във вашия контекст, тогава може просто да искате да съберете пълна DateTimeOffset стойност, като 2013-08-17T13:27:00.000-07:00 вместо това.

person Matt Johnson-Pint    schedule 17.08.2013

Има низове от часови зони, които включват "тихоокеанско стандартно време". Пълният списък можете да намерите тук. http://www.xiirus.net/articles/article-_net-convert-datetime-from-one-timezone-to-another-7e44y.aspx

Всеки обект DateTime може да бъде преобразуван в някаква часова зона -

    TimeZoneInfo timeZoneInfo; 
    DateTime dateTime ; 

    //Set the time zone information to Pacific Standard Time
    timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"); 
    //Get date and time in US Mountain Standard Time 
    dateTime = TimeZoneInfo.ConvertTime(DateTime.Now, timeZoneInfo);
    //Print out the date and time
    Console.WriteLine(dateTime.ToString("yyyy-MM-dd HH-mm-ss")); 

Така че вашият метод може да бъде модифициран като -

static DateTimeOffset ConvertUtcTimeToTimeZone(DateTime dateTime, string toTimeZoneDesc)
{
   return new DateTimeOffset(TimeZoneInfo.ConvertTime(dateTime, TimeZoneInfo.FindSystemTimeZoneById(toTimeZoneDesc)));
}
person Aseem Gautam    schedule 17.08.2013
comment
Вие оставихте местната часова зона да се промъкне в преобразуването, като използвате DateTime.Now и отново, като подадете Unspecified вид DateTime в конструктора DateTimeOffset. - person Matt Johnson-Pint; 18.08.2013
comment
@MattJohnson - това беше само пример, намек е достатъчен за повечето хора. - person Aseem Gautam; 18.08.2013
comment
Може би пример за това как не трябва да го правите... И повечето хора просто ще копират и поставят, без да го обмислят. - person Matt Johnson-Pint; 18.08.2013
comment
Нека бъда ясен, последните два реда трябва да бъдат консолидирани в един ред: return TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, timeZoneInfo);. Това ще върне DateTimeOffset, където времето и отместването са правилни за предоставения timeZoneInfo. - person Matt Johnson-Pint; 18.08.2013
comment
Имаше някои правописни грешки, освен това не виждам проблем с кода. - person Aseem Gautam; 18.08.2013
comment
Това е проблемът с .Net API. Това ви кара да мислите, че всичко е наред, когато не е. Дори и след вашите промени, пак не е наред. Връщането от TimeZoneInfo.ConvertTime, когато се даде DateTime, ще бъде DateTime с .Kind==DateTimeKind.Unspecified. Когато прехвърлите това в конструктора new DateTimeOffset(dateTime), той погрешно ще приеме, че искате локалното отместване. Така че полученото DateTimeOffset няма да има отместването, което съответства на TimeZoneInfo, което искате. - person Matt Johnson-Pint; 18.08.2013
comment
Ето защо предпочитам да използвам Noda Time. Няма да позволява да правите този тип грешки. Не си виновен - извинявай, ако прозвучах грубо. Екипът на .Net BCL е този, който излезе с този податлив на грешки API. - person Matt Johnson-Pint; 18.08.2013