@@ -1888,6 +1888,17 @@ impl Literal {
18881888 date:: date_to_days ( & NaiveDate :: parse_from_str ( & s, "%Y-%m-%d" ) ?) ,
18891889 ) ) ) )
18901890 }
1891+ ( PrimitiveType :: Date , JsonValue :: Number ( number) ) => {
1892+ Ok ( Some ( Literal :: Primitive ( PrimitiveLiteral :: Int (
1893+ number
1894+ . as_i64 ( )
1895+ . ok_or ( Error :: new (
1896+ crate :: ErrorKind :: DataInvalid ,
1897+ "Failed to convert json number to date (days since epoch)" ,
1898+ ) ) ?
1899+ . try_into ( ) ?,
1900+ ) ) ) )
1901+ }
18911902 ( PrimitiveType :: Time , JsonValue :: String ( s) ) => {
18921903 Ok ( Some ( Literal :: Primitive ( PrimitiveLiteral :: Long (
18931904 time:: time_to_microseconds ( & NaiveTime :: parse_from_str ( & s, "%H:%M:%S%.f" ) ?) ,
@@ -3942,4 +3953,44 @@ mod tests {
39423953
39433954 assert_eq ! ( double_sorted, double_expected) ;
39443955 }
3956+
3957+ /// Test Date deserialization from JSON as number (days since epoch).
3958+ ///
3959+ /// This reproduces the scenario from Iceberg Java's TestAddFilesProcedure where:
3960+ /// - Date partition columns have initial_default values in manifests
3961+ /// - These values are serialized as days since epoch (e.g., 18628 for 2021-01-01)
3962+ /// - The JSON schema includes: {"type":"date","initial-default":18628}
3963+ ///
3964+ /// Prior to this fix, Date values in JSON were only parsed from String format ("2021-01-01"),
3965+ /// causing initial_default values to be lost during schema deserialization.
3966+ ///
3967+ /// This test ensures both formats are supported:
3968+ /// - String format: "2021-01-01" (used in table metadata)
3969+ /// - Number format: 18628 (used in initial-default values from add_files)
3970+ ///
3971+ /// See: Iceberg Java TestAddFilesProcedure.addDataPartitionedByDateToPartitioned()
3972+ #[ test]
3973+ fn test_date_from_json_as_number ( ) {
3974+ use serde_json:: json;
3975+
3976+ // Test Date as number (days since epoch) - used in initial-default from add_files
3977+ let date_number = json ! ( 18628 ) ; // 2021-01-01 is 18628 days since 1970-01-01
3978+ let result =
3979+ Literal :: try_from_json ( date_number, & Type :: Primitive ( PrimitiveType :: Date ) ) . unwrap ( ) ;
3980+ assert_eq ! (
3981+ result,
3982+ Some ( Literal :: Primitive ( PrimitiveLiteral :: Int ( 18628 ) ) )
3983+ ) ;
3984+
3985+ // Test Date as string - traditional format
3986+ let date_string = json ! ( "2021-01-01" ) ;
3987+ let result =
3988+ Literal :: try_from_json ( date_string, & Type :: Primitive ( PrimitiveType :: Date ) ) . unwrap ( ) ;
3989+ assert_eq ! (
3990+ result,
3991+ Some ( Literal :: Primitive ( PrimitiveLiteral :: Int ( 18628 ) ) )
3992+ ) ;
3993+
3994+ // Both formats should produce the same Literal value
3995+ }
39453996}
0 commit comments