sql >> Database >  >> RDS >> PostgreSQL

PostgreSQL age()-functie:verschillende/onverwachte resultaten bij het landen in een andere maand

age wordt berekend door de timestamptz_age functie in src/backend/utils/adt/timestamp.c . De opmerking zegt:

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

De code converteert eerst de argumenten naar struct pg_tm variabelen tm1 en tm2 (struct pg_tm is vergelijkbaar met struct tm . van de C-bibliotheek , maar heeft extra tijdzonevelden) en berekent vervolgens het verschil tm per veld.

In het geval van age('2018-07-01','2018-05-20') , zouden de relevante velden van dat verschil er als volgt uitzien:

tm_mday = -19
tm_mon  =   2
tm_year =   0

Nu worden negatieve velden aangepast. voor tm_mday , ziet de code er als volgt uit:

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

Sinds dt1 > dt2 , de else tak wordt genomen, en de code telt het aantal dagen in mei (31) op en vermindert de maand met 1, eindigend met

tm_mday = 12
tm_mon  =  1
tm_year =  0

Dat is het resultaat dat je krijgt.

Op het eerste gezicht lijkt het erop dat tm2->tm_mon is niet de juiste maand om te kiezen, en het zou beter zijn geweest om de vorige maand van het linkerargument te nemen:

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

Maar ik kan niet zeggen of die keuze in alle gevallen beter zou zijn, en in ieder geval vrijwaart de opmerking de functie, dus ik zou aarzelen om het een bug te noemen.

Misschien wil je het opnemen met de hackers-mailinglijst.



  1. Big Query-variabelen instellen, zoals mysql

  2. SQL WHERE tekenreeks LIKE veld

  3. meerdere bestandsindelingen uploaden naar een server met behulp van jsp en het pad opslaan in de database

  4. VBA-code om gegevens op te halen uit Mysql DB in Mac Excel 2011