시간대가 잘못 설정되어 수정 된 경우 사례를 테스트하기 위해 단위 테스트를 작성하려고합니다.
테스트에서 로컬 시간대가 아닌 시간대에 DateTime 객체를 만들어 테스트를 실행하는 사람들이 위치에 관계없이 성공적으로 수행 할 수 있어야합니다.
DateTime 생성자에서 볼 수 있듯이 TimeZone을 현지 시간대, UTC 시간대 또는 지정하지 않도록 설정할 수 있습니다.
PST와 같은 특정 시간대로 DateTime을 어떻게 만듭니 까?
시간대가 잘못 설정되어 수정 된 경우 사례를 테스트하기 위해 단위 테스트를 작성하려고합니다.
테스트에서 로컬 시간대가 아닌 시간대에 DateTime 객체를 만들어 테스트를 실행하는 사람들이 위치에 관계없이 성공적으로 수행 할 수 있어야합니다.
DateTime 생성자에서 볼 수 있듯이 TimeZone을 현지 시간대, UTC 시간대 또는 지정하지 않도록 설정할 수 있습니다.
PST와 같은 특정 시간대로 DateTime을 어떻게 만듭니 까?
답변:
Jon의 답변 은 TimeZone 에 대해 이야기 하지만 TimeZoneInfo를 대신 사용하는 것이 좋습니다 .
개인적으로 나는 가능한 한 UTC로 물건을 유지하는 것을 좋아합니다 (최소한 과거 에는 미래 를 위해 UTC를 저장하면 잠재적 인 문제가 있습니다 ). 다음과 같은 구조를 제안합니다.
public struct DateTimeWithZone
{
private readonly DateTime utcDateTime;
private readonly TimeZoneInfo timeZone;
public DateTimeWithZone(DateTime dateTime, TimeZoneInfo timeZone)
{
var dateTimeUnspec = DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified);
utcDateTime = TimeZoneInfo.ConvertTimeToUtc(dateTimeUnspec, timeZone);
this.timeZone = timeZone;
}
public DateTime UniversalTime { get { return utcDateTime; } }
public TimeZoneInfo TimeZone { get { return timeZone; } }
public DateTime LocalTime
{
get
{
return TimeZoneInfo.ConvertTime(utcDateTime, timeZone);
}
}
}
더 명확하게하기 위해 "TimeZone"이름을 "TimeZoneInfo"로 변경할 수 있습니다. 더 짧은 이름을 선호합니다.
DateTimeOffset 구조는 정확히이 유형의 용도로 작성되었습니다.
참조 : http://msdn.microsoft.com/en-us/library/system.datetimeoffset.aspx
특정 시간대를 사용하여 DateTimeOffset 객체를 만드는 예는 다음과 같습니다.
DateTimeOffset do1 = new DateTimeOffset(2008, 8, 22, 1, 0, 0, new TimeSpan(-5, 0, 0));
여기에있는 다른 답변은 유용하지만 태평양에 구체적으로 액세스하는 방법은 다루지 않습니다.
public static DateTime GmtToPacific(DateTime dateTime)
{
return TimeZoneInfo.ConvertTimeFromUtc(dateTime,
TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"));
}
"태평양 표준시"는 일반적으로 "태평양 일광 절약 시간"과 다른 것을 의미하지만 이상하게도 태평양 표준시를 의미합니다. 실제로 FindSystemTimeZoneById
가져 오기 위해 사용 하는 경우 사용 가능한 속성 중 하나는 해당 시간대가 현재 일광 절약 시간인지 여부를 알려주는 바보입니다.
사용자가 요청한 위치 등에 따라 다른 TimeZone에서 필요한 DateTime을 처리하기 위해 함께 던진 라이브러리에서 더 일반적인 예를 볼 수 있습니다.
https://github.com/b9chris/TimeZoneInfoLib.Net
시간 목록이 Windows 레지스트리에서 제공되므로 Windows 외부에서는 작동하지 않습니다 (예 : Linux의 경우 Mono).
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\
그 아래에는 키 (레지스트리 편집기의 폴더 아이콘)가 있습니다. 그 키의 이름은 당신이 전달하는 것 FindSystemTimeZoneById
입니다. Linux에서는 적절하게 살펴 보지 않은 별도의 Linux 표준 시간대 정의 세트를 사용해야합니다.
Jon Skeet 이 확장 방법으로 웹에 약간 응답 하도록 변경했습니다 . 그것은 매력처럼 하늘빛에도 작용합니다.
public static class DateTimeWithZone
{
private static readonly TimeZoneInfo timeZone;
static DateTimeWithZone()
{
//I added web.config <add key="CurrentTimeZoneId" value="Central Europe Standard Time" />
//You can add value directly into function.
timeZone = TimeZoneInfo.FindSystemTimeZoneById(ConfigurationManager.AppSettings["CurrentTimeZoneId"]);
}
public static DateTime LocalTime(this DateTime t)
{
return TimeZoneInfo.ConvertTime(t, timeZone);
}
}
Jon Skeet의 답변이 마음에 들지만 한 가지만 추가하고 싶습니다. Jon이 ctor가 항상 현지 시간대로 전달 될 것으로 기대하는지 확실하지 않습니다. 그러나 로컬이 아닌 다른 경우에 사용하고 싶습니다.
데이터베이스에서 값을 읽고 데이터베이스의 시간대를 알고 있습니다. 따라서 ctor에서는 데이터베이스의 시간대를 전달합니다. 그러나 현지 시간의 가치를 원합니다. Jon의 LocalTime은 원래 시간대 날짜로 변환 된 원래 날짜를 반환하지 않습니다. 원래 시간대로 변환 된 날짜를 반환합니다 (ctor에 전달한 날짜).
나는이 속성 이름이 그것을 정리한다고 생각합니다 ...
public DateTime TimeInOriginalZone { get { return TimeZoneInfo.ConvertTime(utcDateTime, timeZone); } }
public DateTime TimeInLocalZone { get { return TimeZoneInfo.ConvertTime(utcDateTime, TimeZoneInfo.Local); } }
public DateTime TimeInSpecificZone(TimeZoneInfo tz)
{
return TimeZoneInfo.ConvertTime(utcDateTime, tz);
}
TimeZones 클래스를 사용하면 시간 대별 날짜를 쉽게 만들 수 있습니다.
TimeZoneInfo.ConvertTime(DateTime.Now, TimeZoneInfo.FindSystemTimeZoneById(TimeZones.Paris.Id));