PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Funkcja postgreSQL age():różne/nieoczekiwane wyniki przy lądowaniu w innym miesiącu

age jest obliczana przez timestamptz_age funkcja w src/backend/utils/adt/timestamp.c . Komentarz mówi:

/* timestamptz_age()
 * Calculate time difference while retaining year/month fields.
 * Note that this does not result in an accurate absolute time span
 *  since year and month are out of context once the arithmetic
 *  is done.
 */

Kod najpierw konwertuje argumenty na struct pg_tm zmienne tm1 i tm2 (struct pg_tm jest podobny do struct tm z biblioteki C , ale ma dodatkowe pola strefy czasowej), a następnie oblicza różnicę tm na pole.

W przypadku age('2018-07-01','2018-05-20') , odpowiednie pola tej różnicy będą wyglądać tak:

tm_mday = -19
tm_mon  =   2
tm_year =   0

Teraz pola ujemne są dostosowywane. dla tm_mday , kod wygląda tak:

while (tm->tm_mday < 0)
{
    if (dt1 < dt2)
    {
        tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1];
        tm->tm_mon--;
    }
    else
    {
        tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1];
        tm->tm_mon--;
    }
}

Od dt1 > dt2 , else brana jest gałąź, a kod dodaje liczbę dni w maju (31) i zmniejsza miesiąc o 1, kończąc na

tm_mday = 12
tm_mon  =  1
tm_year =  0

To jest wynik, który otrzymujesz.

Teraz na pierwszy rzut oka wydaje się, że tm2->tm_mon nie jest właściwym miesiącem do wyboru i lepiej byłoby wziąć poprzedni miesiąc z lewego argumentu:

day_tab[isleap(tm1->tm_year)][(tm1->tm_mon + 10) % 12]

Ale nie mogę powiedzieć, czy ten wybór byłby lepszy we wszystkich przypadkach, aw każdym razie komentarz zabezpiecza funkcję, więc waham się nazwać to błędem.

Możesz to zrobić z listą dyskusyjną hakerów.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Połączenie Npgsql z certyfikatami ssl w .net core web api

  2. Jeśli liczba PostgreSQL(*) jest zawsze wolna, jak stronicować złożone zapytania?

  3. Znajdź różnicę między znacznikami czasu w sekundach w PostgreSQL

  4. Generuj serie interwałów tygodniowych dla danego miesiąca

  5. Jak mogę uzyskać wyniki od podmiotu JPA uporządkowane według odległości?