TimeZone을 기반으로 DateTime을 저장하는 모범 사례


16

사용자가 TimeZone을 기준으로 약속을 예약 할 수 있도록 웹 응용 프로그램 개발 그리고 사용자 예약 날짜 시간을 서버 날짜 시간으로 데이터베이스 필드에 저장하고 있습니다. 스케줄 정보를 표시하면서 데이터베이스에서 값을 검색하여 사용자 팀 영역으로 변환했습니다. 코드베이스에서 처리 사용자 시간대를 기준으로 DateTime을 변환하고 있습니다. 이 모범 사례 또는 쉬운 방법이 있습니까?

답변:


33

비계산 프로그래밍에서 가장 어려운 문제 중 하나에 오신 것을 환영합니다. 최종 사용자에게 날짜와 시간을 올바르게 표시합니다.

현실적으로 타임 스탬프는 해석 방법에 관계없이 고정 된 단일 표현으로 저장해야합니다. 아무리 노력해도 항상 모호한 경우가 있으며 고정 표현 없이는 해결할 수 없기 때문입니다. 그리고 약속 일정 예약 중 최악의 사용 사례 중 하나를 선택했습니다. 최악의 일반적인 사용 사례는 항공 여행으로, 여행은 한 시간대에서 시작하여 다른 시간대로 끝날 수 있습니다.

항상 항상 항상 UTC로 저장하고 사용자가 선호하거나 명시 적으로 지정한 시간대로 표시합니다. 가능한 경우 사용자가 타임 스탬프를 입력 할 때 타임 스탬프가 어느 시간대에 있다고 생각하는지 알려주십시오 ( 예 : 명시 적 시간대 필드가 있고 선호하는 시간대로 미리 채움).


1
+1. 그리고 유연합니다. 공통적이고 일관된 범용 표준 참조 시간을 가짐-모든 로컬 영역 "역 참조"가 올바르게 수행됩니다.
radarbob

실제로 약속을 예약하면 UTC로 저장 하지 않을 수있는 몇 번 중 하나입니다. DST 규칙이 변경되거나 UTC에서 오프셋이되면 약속 시간은 어떻게됩니까? 대부분의 경우 약속 시간이 로컬로 동일하게 유지되기를 원하므로 UTC 값이 변경됩니다. UTC를 쉽게 파생시킬 수있는 "TimeInTimeZone + TimeZone"을 나타내는 값을 저장하고 싶을 것입니다. 항공사와 같은 시간대 간 예약에는 제약 조건이있어 두 가지를 모두 사용한다는 의미 일 수 있습니다.
ClockworkMuse

1
아, 그것보다 나 빠진다. 나는 정기적으로 시간 변경 규칙이 다른 나라의 동료들과 회의를합니다. 그렇게되면 정답은 무엇입니까? 사실, 어떤 컴퓨터 :-( 알 수 없다
로스 패터슨에게

3

날짜 / 시간 정보를 처리하는 가장 쉬운 방법은 응용 프로그램의 요구 사항에 따라 다릅니다.

사용자가 날짜와 시간을 입력하고 데이터베이스에 저장하는 것을 제외하고 서버가 해당 날짜 / 시간 정보를 처리하지 않고 입력 한 시간이 표시된 위치에 적응 될 것으로 예상되지 않는 경우 (예 : , 사용자가 "8:00 PM"을 입력하면 세계 어디에서 보든 관계없이 "8:00 PM"으로 표시되어야합니다.) 가장 쉬운 방법은 시간대 정보없이 DateTime을 현지 시간으로 저장하는 것입니다.

반면에 서버가 입력 한 DateTime을 트리거로 사용하여 무언가를 수행하거나 시간을 현재 시간대로 올바르게 조정해야하는 경우 DateTime을 UTC 시간으로 저장하고 로컬로 조정하는 것이 가장 좋습니다. 데이터베이스에서 읽을 때마다 시간 (사용자의 현재 위치)


"현지 시간으로 저장"의 경우 -1, "UTC로 저장"의 경우 +1
Ross Patterson

@RossPatterson : '-1 현지 시간으로 저장'에 대해 '-1을 설명 할 수 있습니까? 나는 그것이 주어진 조건을 감안할 때 그것이 왜 나쁜 생각인지 궁금합니다.
Bart van Ingen Schenau

1
예를 들어, 사용자 로컬 시간을 사용한다는 것은 모든 값이 사실상 수십 개의 서로 다른 데이터 유형 중 하나임을 의미합니다. "TIMESTAMP> '2013-08-27T12 : 00 : 00'"과 같이 데이터베이스 작업을 흥미롭게 수행 할 수 없습니다. 또한 일광 절약 시간제 변환을 언제, 언제 적용할지 알 수 없음을 의미합니다.
로스 패터슨

@RossPatterson : 감사합니다. 대부분의 경우 현지 시간이 올바른 해결책이 아니라는 데 동의합니다.
Bart van Ingen Schenau

2

두 가지 관련 개념을 혼동하지 않는 것이 중요합니다.

실제 특정 시점, 즉 특정 날짜의 특정 시간을 조작하는 경우이를 수행 할 수있는 유일한 방법은 항상 범용 UTC 시간 값을 사용하는 것입니다. 이를 시간대 관련 값으로 저장하지 마십시오. 이 시간 값을 사용자에게 표시 할 때는 항상 해당 시간의 사용자 시간대로 변환하십시오. (시간과 날짜를 모두 시간대에 따라 결정하는 것을 잊지 마십시오.)

다른 개념은 "매주 화요일 오후 8시"와 같은 "시간 표현"이라는 개념입니다. 사람들이 약속을 잡을 수 있도록 구체적으로 언급했으며, 반복적 인 약속이있는 경우 그러한 표현이 필요합니다. 나는 표준 표현 언어를 모르지만, 당신이 무엇을 사용하든, 그것을 지정한 사람의 시간대와 관련이 있습니다. 예를 들어 "매주 화요일 태평양 표준시 기준 오후 8시"와 같이 명시 적으로 작성하는 것이 가장 좋습니다. 시간 표현식의 경우이를 항상 문자열로 저장하고 시스템 시간 형식을 포함하지 않습니다.

내 블로그에서 이에 대한 자세한 내용을 참조하십시오


1

여기에 많은 답변이 UTC로 저장되었음을 나타냅니다. 그러나 이것을 조심하십시오. 예를 들어, 12:00시에 약속을 예약했지만 일광 절약 시간 제로 변경 한 후에 약속이 이루어지면 어떻게됩니까? UTC는 약속이 저장 될 때 dst가 활성화되었는지 여부에 대한 정보를 유지하지 않습니다. UTC에서 다시 계산하는 것은 날짜 시간을 볼 때에 따라 달라지기 때문에 사용자가 여름에 오전 9시에 이메일을 보내면 겨울에 보낸 시간이 오전 8시에 표시되는 크고 유명한 시스템이 많이 발생했습니다. 날짜 시간이 기록 될 때는 켜져 있지 않습니다.

사용자가 항상 선택한 시간을 원한다고 가정하는 것이 훨씬 좋습니다. UTC 변환, 시간 변환, 시간대 정보, 아무것도 없음. 2016 년 3 월 21 일 08 : 00 ~ 12 : 00에 예약하는 것이 바로 그 것입니다. 현지 시간이나 UTC 시간을 사용하지 않지만 지정되지 않은 시간을 사용하지 마십시오 (json에는 z 또는 +가 없으며 기본적으로 .NET에는 DateTime.Kind = DateTimeKind.Unspecified가 있음).

물론, 유스 케이스가 다른 시간대의 다른 사람과 회의를하는 회사이고 회사 달력에서이 정보를 보려고하지만 사용자가 시간대에있는 시간을 볼 수있게하려면 더 복잡해집니다. 다른 시간대 (공급 업체 및 고객)의 다른 사람들에 대해 시간이 정확해야합니다.

이 경우 약속이 데이터베이스에 저장된 시간 , 시간대 dst 포함 여부 를 기록 수도 있습니다 . 이렇게하면 항상 현재 시간 또는 과거의 시간으로 다른 시간으로 현지 시간을 계산할 수 있습니다. 시간대는 정적이지 않기 때문에 훨씬 복잡합니다.

다행히도 http://nodatime.org/ 와 같은 라이브러리가 들어 와서 강력히 권장됩니다. 날짜를 훨씬 더 일관되게 처리합니다. 그럼에도 불구하고 인터페이스를 사용하여 조롱 할 수있는 인터페이스를 사용하여 모든 날짜 시간 변수와 논리를 랩퍼로 래핑하는 것이 좋습니다. 그런 다음 나중에 논리를 전환 할 수 있습니다.


나는 당신의 결론에 동의하지 않지만, 일광 절약 시간제 변경에 따른 정오 회의는 특별한 도전입니다. 정오에 몇 주 후에 예약 된 정오 회의는 앞으로 몇 년이 걸릴 것입니다.
Bent

" 물론 유스 케이스가 다른 시간대의 다른 사람과 회의를하는 회사이고 회사 캘린더에서이 정보를 보려고하지만 사용자가 시간대에있는 시간을 볼 수있게하려면, 더 복잡해집니다. "-거의 모든 회사입니다. 교차 시간대 약속을 무시할 수있는 중국 및 인도 이외의 회사는 거의 없습니다.
로스 패터슨

" 이렇게하면 항상 현재 시간이나 과거의 시간으로 현지 시간을 계산할 수 있습니다. 시간대는 정적이지 않기 때문에 상황이 더욱 복잡해집니다. "-once 당신은 계산을 할 것이라는 것을 받아들이고, 당신은 정말로 시간을위한 단일 표현을 선택해야합니다. UTC, EST (EST5EDT는 아님), IST 등 그러나 동일한 필드에 여러 시간대를 기반으로 한 값을 가질 수 없으며 합법적 인 집계 처리를 수행 할 수 없습니다. 디스플레이 처리, 물론. 그러나 그것은 쉬운 부분입니다.
로스 패터슨

적어도 여전히 UTC로 올바르게 변환 할 수 있습니다. 언제든지이 정보를 사용하여 계산 테이블 또는 값을 소급해서 만들 수 있습니다. 그러나 당신은 다른 길로 갈 수 없습니다. 불행히도 SQL 2016은 기본적으로이를 지원하기 시작하지만 불행히도 여전히 적어도 정확한 레지스트리 데이터는 아니지만 여전히 개선되었습니다.
Arwin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.