sql >> Databáze >  >> RDS >> PostgreSQL

Funkce PostgreSQL age():různé/neočekávané výsledky při přistání v jiném měsíci

age se vypočítá podle timestamptz_age funkce v src/backend/utils/adt/timestamp.c . Komentář říká:

/* 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.
 */

Kód nejprve převede argumenty na struct pg_tm proměnné tm1 a tm2 (struct pg_tm je podobný struct tm knihovny C , ale má další pole časového pásma) a poté vypočítá rozdíl tm na pole.

V případě age('2018-07-01','2018-05-20') , budou příslušná pole tohoto rozdílu vypadat takto:

tm_mday = -19
tm_mon  =   2
tm_year =   0

Nyní jsou záporná pole upravena. pro tm_mday , kód vypadá takto:

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--;
    }
}

Protože dt1 > dt2 , else větev se vezme a kód přidá počet dní v květnu (31) a zkrátí měsíc o 1, což skončí s

tm_mday = 12
tm_mon  =  1
tm_year =  0

To je výsledek, který dostanete.

Nyní se na první pohled zdá, že tm2->tm_mon není správný měsíc na výběr a bylo by lepší vzít předchozí měsíc argumentu vlevo:

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

Nemohu však říci, zda by tato volba byla ve všech případech lepší, a komentář v každém případě funkci odškodní, takže bych váhal označit to za chybu.

Možná budete chtít pokračovat s mailing listem hackerů.



  1. Jak používat GROUP BY a ORDER BY společně v LARAVEL 5.6

  2. Získejte výsledek následujícího dotazu:-

  3. Omezení počtu načtených řádků MySql, Laravel

  4. jQuery Autocomplete (Remote) - příklad