sourcetip

날짜/시간 추가에 대한 기준?

fileupload 2023. 9. 10. 12:29
반응형

날짜/시간 추가에 대한 기준?

날짜/시간 추가 기준을 찾고 있습니다.아무것도 못 찾겠어요.특히 1월 31일과 같은 날짜에 한 달을 더했을 때 어떤 일이 발생해야 하는지 정의하는 스펙을 찾고 싶습니다.정답은 2월 28일(/29일) 맞습니까?3월 1일?3월 2일?

여러 툴(PHP 및 MySQL) 간에 일관성 없는 구현을 경험했으며, 작업의 기반이 되는 일종의 표준을 찾으려고 노력하고 있습니다.

다른 결과:

PHP

$end = strtotime("+1 month", 1314835200);
//1317513600   Sat, 01 Oct 2011 20:00:00 -0400

MySQL

SELECT UNIX_TIMESTAMP(DATE_ADD(FROM_UNIXTIME(1314835200), INTERVAL 1 MONTH));
#1317427200    Fri, 30 Sep 2011 20:00:00 -0400

오라클

SELECT ADD_MONTHS('31-Aug-11', 1) FROM dual;
#30-SEP-11

(형식을 변경해서 죄송합니다, 제 오라클 foo가 약합니다)

자바

Calendar c = Calendar.getInstance();
c.clear();
c.set( 2011, Calendar.AUGUST, 31 );
c.add( Calendar.MONTH, 1 );
c.getTime()
#Fri Sep 30 00:00:00 EDT 2011

POSIX.1-2001 표준에 따르면 다음 달(점증적으로)tm_mon전화하기 mktime까지 조정합니다는 값이 적합할 때까지 조정하는 방법으로 수행됩니다.예를 들어, 2001년 1월 31일부터 다음 달은 2001년 3월 3일입니다.면이기 입니다.tm_mday31의 경우 유효하지 않습니다.tm_mon2월의 1이므로, 1(2)π, π로 됩니다.tm_mon 및 2(3월)및의tm_mday3ℓ의

2000년 1월 31일부터 다음 달은 2000년 3월 2일입니다. 왜냐하면 2월이기 때문입니다.그 해에 29일이 있습니다.다음 달인 12038년 1월부터는 존재하지 않습니다.

표준의 장점은 선택할 수 있는 것이 매우 많다는 것입니다.SQL 표준을 확인해보세요, 다음 달의 다른 의미를 찾을 수 있을 겁니다.ISO 8601이 또 다른 선택지를 줄 수도 있을 것 같습니다.요점은 다양한 행동들이 있다는 것입니다. '다음 달'의 의미는 매우 도메인에 특화되어 있다는 것입니다.

edit: SQL-92에서 처리하는 방법을 찾은 것 같습니다. 1월 31일부터 다음 달을 요청하는 것은 오류인 것 같습니다.

링크:

  • SQL-92: http://www.contrib.andrew.cmu.edu/ ~http/sql/sql1992.txt
  • POSIX: http://pubs.opengroup.org/onlinepubs/9699919799/ (분명히 그 버전은 이제 ISO C를 의미하지만, 이는 명확해 보이지 않습니다.내 기계의 mktime manpage는 분명합니다.)
  • ISO C: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
  • Java: http://download.oracle.com/javase/6/docs/api/java/util/Calendar.html

저는 사실상의 표준이 ISO 8601이라고 생각합니다.안타깝게도 다음과 같은 여러 가지 모호한 점이 있습니다.

날짜 산술이 정의되지 않았습니다.

2001-03-30 + P1M = 2001-04-29 (Add 30 days)
2001-03-30 + P1M = 2001-04-30 (Add 1 mon.)

덧셈은 치환 또는 연관성이 없습니다.

2001-03-30 + P1D + P1M = 2001-04-30
2001-03-30 + P1M + P1D = 2001-05-01

뺄셈은 덧셈의 역이 아닙니다.

소수점 이하 분수의 정밀도는 달라질 수 있습니다.

전체 사양은 http://www.iso.org/iso/catalogue_detail.htm?csnumber=26780 에서 확인할 수 있습니다.

저는 각 제품들이 불가능한 표준을 고수하려고 노력하고 있다고 생각합니다.애매모호한 부분은 해석의 여지가 있기 때문에 모두가 해석을 합니다.이것은 우리에게 Y2K 버그를 열어준 것과 같은 기준입니다!!

저는 날짜/시간을 1970 기준 숫자로 변환하고(UNIX 타임스탬프), 계산을 수행하고 다시 변환하는 구현을 선호합니다.이것이 Oracle/MySQL이 취하는 접근 방식이라고 생각합니다.많은 응용 프로그램에서 매우 중요하고 때로는 중요하기 때문에 이 문제에 더 많은 주의를 기울이지 않은 것이 놀랍습니다.질문 감사합니다!

편집: 읽기를 좀 더 하면서, 저는 다른 날짜/시간 표현과 표준화에 대한 Joe Celko의 생각을 여기서 발견했습니다.

쿼리:

SELECT
ADDDATE(DATE('2010-12-31'), INTERVAL 1 MONTH) 'Dec + Month',
ADDDATE(DATE('2011-01-31'), INTERVAL 1 MONTH) 'Jan + Month',
ADDDATE(DATE('2011-02-28'), INTERVAL 1 MONTH) 'Feb + Month',
ADDDATE(DATE('2011-03-31'), INTERVAL 1 MONTH) 'Mar + Month';

출력:

12월 + 1월 + 2월 + 3월 + 월2011-01-31   2011-02-28   2011-03-28    2011-04-30

나의 결론은:

  1. 입력일 월의 일 수를 계산합니다.
  2. 그 날짜를 입력 날짜에 추가합니다.
  3. 결과일의 일이 결과월의 최대 일 수를 초과하는지 확인합니다.
  4. 예인 경우 결과 일을 결과 월의 최대 일로 변경합니다.

MONTH, YEAR_MONTH 또는 YEAR를 추가하고 결과 날짜가 새 월의 최대 일보다 큰 경우 새 월의 최대 일로 조정됩니다.

원천

여기서 문제는 실제로 월이 투입일로부터 월이라는 것을 언급하지 않는다는 것입니다.

Java의 Joda-Time은 잘못된 날짜가 생성된 이전 유효 날짜를 선택합니다.예를들면,2011-01-31 + P1M = 2011-02-28저는 라이브러리에서이며, 표준이라고 합니다. 저는 이것이 날짜-시간 라이브러리에서 가장 널리 선택된 기본 선택이며, 따라서 사실상의 표준이라고 생각합니다.

ThreeTen/JSR-310은 이를 위한 전략 패턴을 제공하며, 네 가지 선택 사항으로 코드를 참조합니다.

더 재미있는 것은 무엇에 대한 답인가에 대한 질문입니다.2011-01-31 + P1M-1D월을 추가한 다음 유효하지 않은 날짜를 해결한 다음 날짜를 빼면 2011-02-27이 됩니다.하지만 대부분의 사용자들은 기간이 하나의 덩어리로 추가되고 있기 때문에 2011-02-28을 예상하고 있다고 생각합니다.ThreeTen이 이 문제를 어떻게 다루는지 보세요.

날짜/시간 계산 또는 실제 사양에 범용 모범 사례를 작성하는 것을 고려해 보았지만 시간이 별로 없었습니다!

월의 첫날 + 1개월은 다음 달의 첫째 날과 같아야 합니다.SQL Server에서 사용해 보기

          SELECT CAST ('01/01/2012' AS DateTime), DATEADD (m, 1, '01/01/2012')
UNION ALL SELECT CAST ('02/01/2012' AS DateTime), DATEADD (m, 1, '02/01/2012')
UNION ALL SELECT CAST ('03/01/2012' AS DateTime), DATEADD (m, 1, '03/01/2012')
UNION ALL SELECT CAST ('04/01/2012' AS DateTime), DATEADD (m, 1, '04/01/2012')
UNION ALL SELECT CAST ('05/01/2012' AS DateTime), DATEADD (m, 1, '05/01/2012')

결과적으로 다음과 같습니다.

----------------------- -----------------------
2012-01-01              2012-02-01             
2012-02-01              2012-03-01             
2012-03-01              2012-04-01             
2012-04-01              2012-05-01             
2012-05-01              2012-06-01             

이달 말일 + 1개월은 다음달 말일과 같아야 합니다.이것은 다음 달, 현재 달, 10개월 후 등에 적용될 것입니다.

          SELECT CAST ('01/31/2012' AS DateTime), DATEADD (m, 1, '01/31/2012')
UNION ALL SELECT CAST ('01/30/2012' AS DateTime), DATEADD (m, 1, '01/30/2012')
UNION ALL SELECT CAST ('01/29/2012' AS DateTime), DATEADD (m, 1, '01/29/2012')
UNION ALL SELECT CAST ('01/28/2012' AS DateTime), DATEADD (m, 1, '01/28/2012')
UNION ALL SELECT CAST ('01/27/2012' AS DateTime), DATEADD (m, 1, '01/27/2012')
UNION ALL SELECT CAST ('01/26/2012' AS DateTime), DATEADD (m, 1, '01/26/2012')

결과적으로 다음과 같습니다.

----------------------- -----------------------
2012-01-31              2012-02-29             
2012-01-30              2012-02-29             
2012-01-29              2012-02-29             
2012-01-28              2012-02-28             
2012-01-27              2012-02-27             
2012-01-26              2012-02-26             

31, 30, 29가 어떻게 모두 2월 29일이 되는지 보기(2012년은 윤년).

p.s. 나는 읽기 쉽게 하기 위해 시간 부분(모두 0)을 없앴습니다.

널리 받아들여지는 기준은 없습니다.시행 방식이 다른 이유는 기준이 무엇인지에 대해 사람들이 동의할 수 없기 때문입니다.많은 인기 있는 소프트웨어 시스템은 아무도 예상하지 못했던 답을 제공합니다.따라서 시스템이 제공할 내용을 사용자에게 알려주기 위해서는 항상 문서화가 필요합니다.그러나 대부분의 사람들이 기대하는 것을 바탕으로 방법론을 선택합니다.

거리에 있는 대부분의 사람들은 다음과 같은 것에 동의할 것이라고 생각합니다.

  1. '월'을 특정 일 수로 정의할 수 없습니다.그래서...
  2. 1월 31일인데 누군가가 "오늘부터 한 달 후에 만나자"고 하면 2월의 마지막 날을 의미합니다.기본적으로 월에 추가된 후, 초과하지 않고 오늘에 가장 가까운 요일 번호를 찾습니다.

회계에서 예외가 발생하는데, 한 달은 30일을 의미하기도 합니다.

편집: 저는 이 근처에 있는 몇몇 사람들에게 "3월 31일인데 오늘부터 한 달 뒤에 만난다고 하면 무슨 요일에 만날 거예요?"라고 물었습니다.대부분이 4월 30일이라고 했지만, 4주가 남았기 때문에 일부는 4월 28일이라고 답했습니다.소수는 업무 일정을 해석하며 '이번 주중에 만나면 같은 주중에 다시 만날 수 있을 것'이라고 생각하고 있었습니다.기본적으로 그 달의 마지막 목요일에 만났고, 한 달 후에 만나기로 했다면, 그 달의 마지막 목요일일 것입니다.

자, 여기 있습니다. :\

mysql date 함수를 사용해 보십시오.

선택추가일자('2011-01-31', 인터벌 1개월) // 2011-02-28

윤년포함입력일자

선택추가일자('2012-01-31', 인터벌 1개월) // 2012-02-29

에서.NET은 시스템의 동작을 프레임워크화합니다.날짜 시간.Add Months는 다음과 같습니다.

AddMonths 메서드는 윤년과 한 달의 일 수를 고려하여 결과 월과 연도를 계산한 다음 결과 DateTime 개체의 일 부분을 조정합니다.결과 일이 결과 월에 유효한 일이 아닌 경우 결과 월의 마지막 유효 일이 사용됩니다.예를 들어 3월 31일 + 1개월 = [4월 31일이 아닌] 4월 30일입니다.

정확한 작동 방식을 테스트했습니다.

Console.WriteLine(new DateTime(2008,2,27).AddMonths(1));
Console.WriteLine(new DateTime(2008,2,28).AddMonths(1));
Console.WriteLine(new DateTime(2008,2,29).AddMonths(1));
Console.WriteLine(new DateTime(2011,2,27).AddMonths(1));
Console.WriteLine(new DateTime(2011,2,28).AddMonths(1));
Console.WriteLine(new DateTime(2008,1,30).AddMonths(1));
Console.WriteLine(new DateTime(2008,1,31).AddMonths(1));
Console.WriteLine(new DateTime(2011,1,30).AddMonths(1));
Console.WriteLine(new DateTime(2011,1,31).AddMonths(1));
/* output
3/27/2008 12:00:00 AM
3/28/2008 12:00:00 AM
3/29/2008 12:00:00 AM
3/27/2011 12:00:00 AM
3/28/2011 12:00:00 AM
2/29/2008 12:00:00 AM
2/29/2008 12:00:00 AM
2/28/2011 12:00:00 AM
2/28/2011 12:00:00 AM
    */

언급URL : https://stackoverflow.com/questions/7614361/standards-for-date-time-addition

반응형