PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Функция PostgreSQL age():различни/неочаквани резултати при кацане в друг месец

age се изчислява чрез timestamptz_age функция в src/backend/utils/adt/timestamp.c . Коментарът гласи:

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

Кодът първо преобразува аргументите в struct pg_tm променливи tm1 и tm2 (struct pg_tm е подобен на struct tm на C библиотеката , но има допълнителни полета за часова зона) и след това изчислява разликата tm на поле.

В случай на age('2018-07-01','2018-05-20') , съответните полета на тази разлика ще изглеждат така:

tm_mday = -19
tm_mon  =   2
tm_year =   0

Сега отрицателните полета се коригират. за tm_mday , кодът изглежда така:

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

Тъй като dt1 > dt2 , else клонът се взема и кодът добавя броя на дните през май (31) и намалява месеца с 1, завършвайки с

tm_mday = 12
tm_mon  =  1
tm_year =  0

Това е резултатът, който получавате.

Сега на пръв поглед изглежда, че tm2->tm_mon не е правилният месец за избор и би било по-добре да вземете предходния месец от левия аргумент:

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

Но не мога да кажа дали този избор би бил по-добър във всички случаи и във всеки случай коментарът обезщетява функцията, така че бих се поколебал да го нарека грешка.

Може да искате да го включите в пощенския списък на хакерите.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Комбинации от заявки с вложен масив от записи в тип данни JSON

  2. Как да направите избор с масив съдържа клауза за стойност в psql

  3. rails postgres ГРЕШКА:невалиден входен синтаксис за тип двойна точност

  4. Разбиране и четене на системния каталог на PostgreSQL

  5. Безопасно преименувайте таблици, като използвате колони от сериен първичен ключ