darshil929 opened a new issue, #27212:
URL: https://github.com/apache/datafusion/issues/27212

   ### Describe the bug
   
   `extract(epoch from <interval>)` returns the wrong number of seconds once an 
interval reaches one year. DataFusion treats every 12 months as 360 days (12 
months of 30 days each). PostgreSQL and DuckDB count each whole year as 365.25 
days and only use 30 days for the months left over, so for a one year interval 
DataFusion comes out 5.25 days short.
   
   Intervals shorter than a year give the same answer in all three.
   
   ### To Reproduce
   
   In `datafusion-cli` built from main:
   
   ```sql
   SELECT s AS input, extract(epoch FROM i) AS epoch_seconds
   FROM (VALUES
     ('11 months', INTERVAL '11 months'),
     ('1 year', INTERVAL '1 year'),
     ('14 months', INTERVAL '14 months'),
     ('-14 months', INTERVAL '-14 months'),
     ('1 year 1 day', INTERVAL '1 year 1 day')
   ) AS t(s, i);
   ```
   
   ```
   +--------------+---------------+
   | input        | epoch_seconds |
   +--------------+---------------+
   | 11 months    | 28512000.0    |
   | 1 year       | 31104000.0    |
   | 14 months    | 36288000.0    |
   | -14 months   | -36288000.0   |
   | 1 year 1 day | 31190400.0    |
   +--------------+---------------+
   ```
   
   The same query in PostgreSQL 18:
   
   ```
       input     |  epoch_seconds
   --------------+------------------
    11 months    |  28512000.000000
    1 year       |  31557600.000000
    14 months    |  36741600.000000
    -14 months   | -36741600.000000
    1 year 1 day |  31644000.000000
   (5 rows)
   ```
   
   DuckDB returns the same numbers as PostgreSQL for every row.
   
   The `Interval(YearMonth)` type behaves the same way:
   
   ```sql
   SELECT extract(epoch FROM arrow_cast('1 year', 'Interval(YearMonth)'));
   -- 31104000.0
   ```
   
   ### Expected behavior
   
   Whole years in an interval should count as 365.25 days and the remaining 
months as 30 days each, the way PostgreSQL and DuckDB do it. With that, `1 
year` would return 31557600 and `14 months` would return 36741600 (365.25 days 
plus 60 days). Results for intervals under a year would stay as they are.
   
   ### Additional context
   
   The interval conversion is in `epoch()` in `date_part.rs`. Its comment says 
the 30 day month follows PostgreSQL. PostgreSQL does use 30 days for the 
leftover months, but it counts the whole years in an interval as 365.25 days, 
while DataFusion currently applies the 30 day rule to all of the months.
   
   I'd like to work on the fix, with sqllogictest coverage for these cases, 
once we've settled on an approach.
   
   ### Willingness to contribute
   
   I would like to contribute a fix for this bug, but request guidance from the 
DataFusion community


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to