diff --git a/CHANGELOG.md b/CHANGELOG.md index 29b7332910d..cc485ac81de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,7 +64,8 @@ - [Added .floor, .ceil, .trunc to the in-memory `Decimal` column.][10887] - [Added vectorized .round to the in-memory `Decimal` column.][10912] - [`select_into_database_table` no longer defaults the primary key to the first - column][11120] + column.][11120] +- [Added `format` parameter to `Decimal.parse`.][11205] [10614]: https://github.com/enso-org/enso/pull/10614 [10660]: https://github.com/enso-org/enso/pull/10660 @@ -77,6 +78,7 @@ [10887]: https://github.com/enso-org/enso/pull/10887 [10912]: https://github.com/enso-org/enso/pull/10912 [11120]: https://github.com/enso-org/enso/pull/11120 +[11205]: https://github.com/enso-org/enso/pull/11205 #### Enso Language & Runtime diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Decimal.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Decimal.enso index df6836484c1..234cdda42dd 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Decimal.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Decimal.enso @@ -1116,10 +1116,13 @@ type Decimal Arguments: - text: The text to parse into a `Decimal`. - locale: The locale that specifies the format to use when parsing. + - format: The Java-style format to use to parse the string. ! Error Conditions - If `text` is incorrectly formatted, a `Number_Parse_Error` is thrown. + - If `format` is incorrectly formatted (or does not match the `locale`, + an `Illegal_Argument` is thrown. > Example Parse a `Decimal` with no local specifier. @@ -1144,11 +1147,21 @@ type Decimal Decimal.parse "123.456.789,87654" locale=Locale.italy # => 123456789.87654 - parse : Text -> Locale | Nothing -> Decimal ! Number_Parse_Error - parse text locale:(Locale | Nothing)=Nothing -> Decimal ! Number_Parse_Error = case locale of - Nothing -> Decimal.from_text text - Locale.Value java_locale -> Panic.catch ParseException ((NumberFormat.getInstance java_locale).parse text) _-> - Error.throw (Number_Parse_Error.Error text) + + > Example + Parse a `Decimal` with an explicit negative number format. + + Decimal.parse "(123,456,789.654)" format="###,###.##;(###,###.##)" + # => -123456789.654 + parse : Text -> Locale | Nothing -> Decimal ! Number_Parse_Error ! Illegal_Argument + parse text locale:Locale=Locale.default format:Text="" -> Decimal ! Number_Parse_Error ! Illegal_Argument = + Illegal_Argument.handle_java_exception <| + # `getInstance` returns `DecimalFormat` or a subclass of `DecimalFormat`. + decimal_format = NumberFormat.getInstance locale.java_locale + decimal_format.applyLocalizedPattern format + decimal_format.setParseBigDecimal True + Panic.catch ParseException (Decimal.Value (decimal_format.parse text)) _-> + Error.throw (Number_Parse_Error.Error text) ## PRIVATE precision : Integer diff --git a/test/Base_Tests/src/Data/Decimal_Spec.enso b/test/Base_Tests/src/Data/Decimal_Spec.enso index cba44907a4f..3465ce9cd85 100644 --- a/test/Base_Tests/src/Data/Decimal_Spec.enso +++ b/test/Base_Tests/src/Data/Decimal_Spec.enso @@ -798,14 +798,26 @@ add_specs suite_builder = d.format format="#,##.##" locale=Locale.italy . should_equal "1.23.45.67.89,88" group_builder.specify "should parse correctly" <| - Decimal.parse "123456789.87654" . should_equal 123456789.87654 - Decimal.parse "123,456,789.87654" locale=Locale.default . should_equal 123456789.87654 - Decimal.parse "123,456,789.87654" locale=Locale.us . should_equal 123456789.87654 - Decimal.parse "123.456.789,87654" locale=Locale.italy . should_equal 123456789.87654 + Decimal.parse "123,456,789.87654" . should_equal (dec "123456789.87654") + Decimal.parse "123.456.789,87654" locale=Locale.italy . should_equal (dec "123456789.87654") + + Decimal.parse "123,456,789.88" format="#,###.##" . should_equal (dec "123456789.88") + Decimal.parse "123.456.789,88" format="#.###,##" locale=Locale.italy . should_equal (dec "123456789.88") + Decimal.parse "1,23,45,67,89.88" format="#,##.##" . should_equal (dec "123456789.88") + Decimal.parse "1.23.45.67.89,88" format="#.##,##" locale=Locale.italy . should_equal (dec "123456789.88") + + Decimal.parse "123.456.789,88" format="#,###.##" locale=Locale.italy . should_fail_with Illegal_Argument + Decimal.parse "123,456,789.88" format="#.###,##" . should_fail_with Illegal_Argument + Decimal.parse "123,456,789.87654" locale=Locale.italy . should_equal 123.456 Decimal.parse "123.456.789,87654" locale=Locale.us . should_equal 123.456 - Decimal.parse "123,456,789.87654" . should_fail_with Number_Parse_Error + Decimal.parse "123,456,789.654" format="###,###.##;-###,###.##" . should_equal 123456789.654 + Decimal.parse "-123,456,789.654" format="###,###.##;-###,###.##" . should_equal -123456789.654 + Decimal.parse "(123,456,789.654)" format="###,###.##;-###,###.##" . should_fail_with Number_Parse_Error + Decimal.parse "123,456,789.654" format="###,###.##;(###,###.##)" . should_equal 123456789.654 + Decimal.parse "-123,456,789.654" format="###,###.##;(###,###.##)" . should_fail_with Number_Parse_Error + Decimal.parse "(123,456,789.654)" format="###,###.##;(###,###.##)" . should_equal -123456789.654 suite_builder.group "(Decimal_Spec) signs" group_builder-> group_builder.specify "should calculate abs correctly" <|