sql >> Databasteknik >  >> RDS >> PostgreSQL

PostgreSQL age() funktion:olika/oväntade resultat när man landar i en annan månad

age beräknas av timestamptz_age funktion i src/backend/utils/adt/timestamp.c . Kommentaren säger:

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

Koden konverterar först argumenten till struct pg_tm variabler tm1 och tm2 (struct pg_tm liknar C-bibliotekets struct tm , men har ytterligare tidszonsfält) och beräknar sedan skillnaden tm per fält.

I fallet med age('2018-07-01','2018-05-20') , de relevanta fälten för den skillnaden skulle se ut så här:

tm_mday = -19
tm_mon  =   2
tm_year =   0

Nu är negativa fält justerade. för tm_mday , koden ser ut så här:

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

Sedan dt1 > dt2 , den else gren tas, och koden lägger till antalet dagar i maj (31) och minskar månaden med 1, vilket slutar med

tm_mday = 12
tm_mon  =  1
tm_year =  0

Det är resultatet du får.

Nu vid första anblicken verkar det som tm2->tm_mon är inte rätt månad att välja, och det hade varit bättre att ta föregående månad av vänsterargumentet:

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

Men jag kan inte säga om det valet skulle vara bättre i alla fall, och i vilket fall som helst frigör kommentaren funktionen, så jag skulle tveka att kalla det en bugg.

Du kanske vill ta upp det med hackarnas e-postlista.



  1. MySQL - Hämtar lägsta värde

  2. Hur håller man en enda SQL Server-anslutningsinstans öppen för flera begäranden i C#?

  3. neo4j prestanda jämfört med mysql (hur kan det förbättras?)

  4. django.db.utils.IntegrityError:duplicerat nyckelvärde bryter mot den unika begränsningen spirit_category_category_pkey