diff --git a/src/vtlengine/DataTypes/TimeHandling.py b/src/vtlengine/DataTypes/TimeHandling.py index 204a449b2..b46934cdb 100644 --- a/src/vtlengine/DataTypes/TimeHandling.py +++ b/src/vtlengine/DataTypes/TimeHandling.py @@ -17,6 +17,18 @@ PERIOD_INDICATORS = ["A", "S", "Q", "M", "W", "D"] +class TimePeriodConfig: + _representation = "vtl" # Default representation + + @classmethod + def set_representation(cls, representation: str) -> None: + cls._representation = representation + + @classmethod + def get_representation(cls) -> str: + return cls._representation + + def date_to_period(date_value: date, period_indicator: str) -> Any: if period_indicator == "A": return TimePeriodHandler(f"{date_value.year}A") @@ -387,6 +399,18 @@ def natural_representation(self) -> str: period_number_str = str(self.period_number) return f"{self.year}-{self.period_indicator}{period_number_str}" + def external_representation(self) -> str: + """Return the representation based on the configured TimePeriodConfig.""" + representation = TimePeriodConfig.get_representation() + if representation == "vtl": + return self.vtl_representation() + elif representation == "sdmx_gregorian": + return self.sdmx_gregorian_representation() + elif representation == "sdmx_reporting": + return self.sdmx_reporting_representation() + else: + return self.natural_representation() + class TimeIntervalHandler: _date1: str = "0" diff --git a/src/vtlengine/DataTypes/__init__.py b/src/vtlengine/DataTypes/__init__.py index 805cd6d2e..6e79c6562 100644 --- a/src/vtlengine/DataTypes/__init__.py +++ b/src/vtlengine/DataTypes/__init__.py @@ -144,12 +144,13 @@ def explicit_cast(cls, value: Any, from_type: Any) -> str: Boolean, String, Date, - TimePeriod, TimeInterval, }: return str(value) if from_type == Duration: return _SHORTCODE_TO_ISO.get(str(value), str(value)) + elif from_type == TimePeriod: + return TimePeriodHandler(str(value)).external_representation() raise RunTimeError( "2-1-5-1", diff --git a/src/vtlengine/files/output/_time_period_representation.py b/src/vtlengine/files/output/_time_period_representation.py index dd77f12b6..56fad1cbf 100644 --- a/src/vtlengine/files/output/_time_period_representation.py +++ b/src/vtlengine/files/output/_time_period_representation.py @@ -2,7 +2,7 @@ from typing import Union from vtlengine.DataTypes import TimePeriod -from vtlengine.DataTypes.TimeHandling import TimePeriodHandler +from vtlengine.DataTypes.TimeHandling import TimePeriodConfig, TimePeriodHandler from vtlengine.Exceptions import InputValidationException from vtlengine.Model import Dataset, Scalar @@ -21,6 +21,9 @@ def check_value(cls, value: str) -> "TimePeriodRepresentation": raise InputValidationException( code="0-1-1-15", value=value, valid_options=valid_options ) + + TimePeriodConfig.set_representation(value) + return cls(value) diff --git a/tests/Cast/data/Dataset/output/GL_563_1-1.csv b/tests/Cast/data/Dataset/output/GL_563_1-1.csv index b9e5e78d8..bd4b3ea02 100644 --- a/tests/Cast/data/Dataset/output/GL_563_1-1.csv +++ b/tests/Cast/data/Dataset/output/GL_563_1-1.csv @@ -1,15 +1,15 @@ FREQ,MEASURE,REF_AREA,TIME_PERIOD,UNIT_MEASURE,year_id,OBS_VALUE,ADJUSTMENT,BASE_PER,DECIMALS,OBS_STATUS,UNIT_MULT -Q,HPI_YDH,HUN,2007-Q1,IX,2007A,128.791663747366,S,2015,1,A,0 -Q,HPI_YDH,HUN,2007-Q2,IX,2007A,135.068262557786,S,2015,1,A,0 -Q,HPI_YDH,HUN,2007-Q3,IX,2007A,137.007469129715,S,2015,1,A,0 -Q,HPI_YDH,HUN,2007-Q4,IX,2007A,133.095968661608,S,2015,1,A,0 -Q,HPI_YDH,HUN,2008-Q1,IX,2008A,133.03554880574,S,2015,1,A,0 -Q,HPI_YDH,HUN,2008-Q2,IX,2008A,134.223860470646,S,2015,1,A,0 -Q,HPI_YDH,HUN,2008-Q3,IX,2008A,133.560759222016,S,2015,1,A,0 -Q,HPI_YDH,HUN,2008-Q4,IX,2008A,126.58631498202,S,2015,1,A,0 -Q,HPI_YDH,HUN,2009-Q1,IX,2009A,129.175020241349,S,2015,1,A,0 -Q,HPI_YDH,HUN,2009-Q2,IX,2009A,128.069036228621,S,2015,1,A,0 -Q,HPI_YDH,HUN,2009-Q3,IX,2009A,120.538647006447,S,2015,1,A,0 -Q,HPI_YDH,HUN,2009-Q4,IX,2009A,122.981069897426,S,2015,1,A,0 -Q,HPI_YDH,HUN,2010-Q1,IX,2010A,120.008425982046,S,2015,1,A,0 -Q,HPI_YDH,HUN,2010-Q2,IX,2010A,117.718433849041,S,2015,1,A,0 +Q,HPI_YDH,HUN,2007-Q1,IX,2007,128.791663747366,S,2015,1,A,0 +Q,HPI_YDH,HUN,2007-Q2,IX,2007,135.068262557786,S,2015,1,A,0 +Q,HPI_YDH,HUN,2007-Q3,IX,2007,137.007469129715,S,2015,1,A,0 +Q,HPI_YDH,HUN,2007-Q4,IX,2007,133.095968661608,S,2015,1,A,0 +Q,HPI_YDH,HUN,2008-Q1,IX,2008,133.03554880574,S,2015,1,A,0 +Q,HPI_YDH,HUN,2008-Q2,IX,2008,134.223860470646,S,2015,1,A,0 +Q,HPI_YDH,HUN,2008-Q3,IX,2008,133.560759222016,S,2015,1,A,0 +Q,HPI_YDH,HUN,2008-Q4,IX,2008,126.58631498202,S,2015,1,A,0 +Q,HPI_YDH,HUN,2009-Q1,IX,2009,129.175020241349,S,2015,1,A,0 +Q,HPI_YDH,HUN,2009-Q2,IX,2009,128.069036228621,S,2015,1,A,0 +Q,HPI_YDH,HUN,2009-Q3,IX,2009,120.538647006447,S,2015,1,A,0 +Q,HPI_YDH,HUN,2009-Q4,IX,2009,122.981069897426,S,2015,1,A,0 +Q,HPI_YDH,HUN,2010-Q1,IX,2010,120.008425982046,S,2015,1,A,0 +Q,HPI_YDH,HUN,2010-Q2,IX,2010,117.718433849041,S,2015,1,A,0 diff --git a/tests/Cast/data/Dataset/output/GL_563_1-2.csv b/tests/Cast/data/Dataset/output/GL_563_1-2.csv index c4b8bca0b..8c14e1afd 100644 --- a/tests/Cast/data/Dataset/output/GL_563_1-2.csv +++ b/tests/Cast/data/Dataset/output/GL_563_1-2.csv @@ -1,15 +1,15 @@ FREQ,MEASURE,REF_AREA,TIME_PERIOD,UNIT_MEASURE,year_id,year_id2,OBS_VALUE,ADJUSTMENT,BASE_PER,DECIMALS,OBS_STATUS,UNIT_MULT -Q,HPI_YDH,HUN,2007-Q1,IX,2007A,2007A,128.791663747366,S,2015,1,A,0 -Q,HPI_YDH,HUN,2007-Q2,IX,2007A,2007A,135.068262557786,S,2015,1,A,0 -Q,HPI_YDH,HUN,2007-Q3,IX,2007A,2007A,137.007469129715,S,2015,1,A,0 -Q,HPI_YDH,HUN,2007-Q4,IX,2007A,2007A,133.095968661608,S,2015,1,A,0 -Q,HPI_YDH,HUN,2008-Q1,IX,2008A,2008A,133.03554880574,S,2015,1,A,0 -Q,HPI_YDH,HUN,2008-Q2,IX,2008A,2008A,134.223860470646,S,2015,1,A,0 -Q,HPI_YDH,HUN,2008-Q3,IX,2008A,2008A,133.560759222016,S,2015,1,A,0 -Q,HPI_YDH,HUN,2008-Q4,IX,2008A,2008A,126.58631498202,S,2015,1,A,0 -Q,HPI_YDH,HUN,2009-Q1,IX,2009A,2009A,129.175020241349,S,2015,1,A,0 -Q,HPI_YDH,HUN,2009-Q2,IX,2009A,2009A,128.069036228621,S,2015,1,A,0 -Q,HPI_YDH,HUN,2009-Q3,IX,2009A,2009A,120.538647006447,S,2015,1,A,0 -Q,HPI_YDH,HUN,2009-Q4,IX,2009A,2009A,122.981069897426,S,2015,1,A,0 -Q,HPI_YDH,HUN,2010-Q1,IX,2010A,2010A,120.008425982046,S,2015,1,A,0 -Q,HPI_YDH,HUN,2010-Q2,IX,2010A,2010A,117.718433849041,S,2015,1,A,0 +Q,HPI_YDH,HUN,2007-Q1,IX,2007,2007,128.791663747366,S,2015,1,A,0 +Q,HPI_YDH,HUN,2007-Q2,IX,2007,2007,135.068262557786,S,2015,1,A,0 +Q,HPI_YDH,HUN,2007-Q3,IX,2007,2007,137.007469129715,S,2015,1,A,0 +Q,HPI_YDH,HUN,2007-Q4,IX,2007,2007,133.095968661608,S,2015,1,A,0 +Q,HPI_YDH,HUN,2008-Q1,IX,2008,2008,133.03554880574,S,2015,1,A,0 +Q,HPI_YDH,HUN,2008-Q2,IX,2008,2008,134.223860470646,S,2015,1,A,0 +Q,HPI_YDH,HUN,2008-Q3,IX,2008,2008,133.560759222016,S,2015,1,A,0 +Q,HPI_YDH,HUN,2008-Q4,IX,2008,2008,126.58631498202,S,2015,1,A,0 +Q,HPI_YDH,HUN,2009-Q1,IX,2009,2009,129.175020241349,S,2015,1,A,0 +Q,HPI_YDH,HUN,2009-Q2,IX,2009,2009,128.069036228621,S,2015,1,A,0 +Q,HPI_YDH,HUN,2009-Q3,IX,2009,2009,120.538647006447,S,2015,1,A,0 +Q,HPI_YDH,HUN,2009-Q4,IX,2009,2009,122.981069897426,S,2015,1,A,0 +Q,HPI_YDH,HUN,2010-Q1,IX,2010,2010,120.008425982046,S,2015,1,A,0 +Q,HPI_YDH,HUN,2010-Q2,IX,2010,2010,117.718433849041,S,2015,1,A,0 diff --git a/tests/Cast/test_cast.py b/tests/Cast/test_cast.py index 205249ba4..9633f60a3 100644 --- a/tests/Cast/test_cast.py +++ b/tests/Cast/test_cast.py @@ -383,9 +383,9 @@ class TestCastTimePeriodToString: @pytest.mark.parametrize( "input_val, expected", [ - ("2024A", "2024A"), - ("2024-Q1", "2024-Q1"), - ("2020A", "2020A"), + ("2024A", "2024"), + ("2024-Q1", "2024Q1"), + ("2020A", "2020"), ("2020Q1", "2020Q1"), (None, None), ], diff --git a/tests/TimePeriod/data/DataSet/output/GL_563_1-1.csv b/tests/TimePeriod/data/DataSet/output/GL_563_1-1.csv index b9e5e78d8..bd4b3ea02 100644 --- a/tests/TimePeriod/data/DataSet/output/GL_563_1-1.csv +++ b/tests/TimePeriod/data/DataSet/output/GL_563_1-1.csv @@ -1,15 +1,15 @@ FREQ,MEASURE,REF_AREA,TIME_PERIOD,UNIT_MEASURE,year_id,OBS_VALUE,ADJUSTMENT,BASE_PER,DECIMALS,OBS_STATUS,UNIT_MULT -Q,HPI_YDH,HUN,2007-Q1,IX,2007A,128.791663747366,S,2015,1,A,0 -Q,HPI_YDH,HUN,2007-Q2,IX,2007A,135.068262557786,S,2015,1,A,0 -Q,HPI_YDH,HUN,2007-Q3,IX,2007A,137.007469129715,S,2015,1,A,0 -Q,HPI_YDH,HUN,2007-Q4,IX,2007A,133.095968661608,S,2015,1,A,0 -Q,HPI_YDH,HUN,2008-Q1,IX,2008A,133.03554880574,S,2015,1,A,0 -Q,HPI_YDH,HUN,2008-Q2,IX,2008A,134.223860470646,S,2015,1,A,0 -Q,HPI_YDH,HUN,2008-Q3,IX,2008A,133.560759222016,S,2015,1,A,0 -Q,HPI_YDH,HUN,2008-Q4,IX,2008A,126.58631498202,S,2015,1,A,0 -Q,HPI_YDH,HUN,2009-Q1,IX,2009A,129.175020241349,S,2015,1,A,0 -Q,HPI_YDH,HUN,2009-Q2,IX,2009A,128.069036228621,S,2015,1,A,0 -Q,HPI_YDH,HUN,2009-Q3,IX,2009A,120.538647006447,S,2015,1,A,0 -Q,HPI_YDH,HUN,2009-Q4,IX,2009A,122.981069897426,S,2015,1,A,0 -Q,HPI_YDH,HUN,2010-Q1,IX,2010A,120.008425982046,S,2015,1,A,0 -Q,HPI_YDH,HUN,2010-Q2,IX,2010A,117.718433849041,S,2015,1,A,0 +Q,HPI_YDH,HUN,2007-Q1,IX,2007,128.791663747366,S,2015,1,A,0 +Q,HPI_YDH,HUN,2007-Q2,IX,2007,135.068262557786,S,2015,1,A,0 +Q,HPI_YDH,HUN,2007-Q3,IX,2007,137.007469129715,S,2015,1,A,0 +Q,HPI_YDH,HUN,2007-Q4,IX,2007,133.095968661608,S,2015,1,A,0 +Q,HPI_YDH,HUN,2008-Q1,IX,2008,133.03554880574,S,2015,1,A,0 +Q,HPI_YDH,HUN,2008-Q2,IX,2008,134.223860470646,S,2015,1,A,0 +Q,HPI_YDH,HUN,2008-Q3,IX,2008,133.560759222016,S,2015,1,A,0 +Q,HPI_YDH,HUN,2008-Q4,IX,2008,126.58631498202,S,2015,1,A,0 +Q,HPI_YDH,HUN,2009-Q1,IX,2009,129.175020241349,S,2015,1,A,0 +Q,HPI_YDH,HUN,2009-Q2,IX,2009,128.069036228621,S,2015,1,A,0 +Q,HPI_YDH,HUN,2009-Q3,IX,2009,120.538647006447,S,2015,1,A,0 +Q,HPI_YDH,HUN,2009-Q4,IX,2009,122.981069897426,S,2015,1,A,0 +Q,HPI_YDH,HUN,2010-Q1,IX,2010,120.008425982046,S,2015,1,A,0 +Q,HPI_YDH,HUN,2010-Q2,IX,2010,117.718433849041,S,2015,1,A,0 diff --git a/tests/TimePeriod/data/DataSet/output/GL_563_1-2.csv b/tests/TimePeriod/data/DataSet/output/GL_563_1-2.csv index c4b8bca0b..8c14e1afd 100644 --- a/tests/TimePeriod/data/DataSet/output/GL_563_1-2.csv +++ b/tests/TimePeriod/data/DataSet/output/GL_563_1-2.csv @@ -1,15 +1,15 @@ FREQ,MEASURE,REF_AREA,TIME_PERIOD,UNIT_MEASURE,year_id,year_id2,OBS_VALUE,ADJUSTMENT,BASE_PER,DECIMALS,OBS_STATUS,UNIT_MULT -Q,HPI_YDH,HUN,2007-Q1,IX,2007A,2007A,128.791663747366,S,2015,1,A,0 -Q,HPI_YDH,HUN,2007-Q2,IX,2007A,2007A,135.068262557786,S,2015,1,A,0 -Q,HPI_YDH,HUN,2007-Q3,IX,2007A,2007A,137.007469129715,S,2015,1,A,0 -Q,HPI_YDH,HUN,2007-Q4,IX,2007A,2007A,133.095968661608,S,2015,1,A,0 -Q,HPI_YDH,HUN,2008-Q1,IX,2008A,2008A,133.03554880574,S,2015,1,A,0 -Q,HPI_YDH,HUN,2008-Q2,IX,2008A,2008A,134.223860470646,S,2015,1,A,0 -Q,HPI_YDH,HUN,2008-Q3,IX,2008A,2008A,133.560759222016,S,2015,1,A,0 -Q,HPI_YDH,HUN,2008-Q4,IX,2008A,2008A,126.58631498202,S,2015,1,A,0 -Q,HPI_YDH,HUN,2009-Q1,IX,2009A,2009A,129.175020241349,S,2015,1,A,0 -Q,HPI_YDH,HUN,2009-Q2,IX,2009A,2009A,128.069036228621,S,2015,1,A,0 -Q,HPI_YDH,HUN,2009-Q3,IX,2009A,2009A,120.538647006447,S,2015,1,A,0 -Q,HPI_YDH,HUN,2009-Q4,IX,2009A,2009A,122.981069897426,S,2015,1,A,0 -Q,HPI_YDH,HUN,2010-Q1,IX,2010A,2010A,120.008425982046,S,2015,1,A,0 -Q,HPI_YDH,HUN,2010-Q2,IX,2010A,2010A,117.718433849041,S,2015,1,A,0 +Q,HPI_YDH,HUN,2007-Q1,IX,2007,2007,128.791663747366,S,2015,1,A,0 +Q,HPI_YDH,HUN,2007-Q2,IX,2007,2007,135.068262557786,S,2015,1,A,0 +Q,HPI_YDH,HUN,2007-Q3,IX,2007,2007,137.007469129715,S,2015,1,A,0 +Q,HPI_YDH,HUN,2007-Q4,IX,2007,2007,133.095968661608,S,2015,1,A,0 +Q,HPI_YDH,HUN,2008-Q1,IX,2008,2008,133.03554880574,S,2015,1,A,0 +Q,HPI_YDH,HUN,2008-Q2,IX,2008,2008,134.223860470646,S,2015,1,A,0 +Q,HPI_YDH,HUN,2008-Q3,IX,2008,2008,133.560759222016,S,2015,1,A,0 +Q,HPI_YDH,HUN,2008-Q4,IX,2008,2008,126.58631498202,S,2015,1,A,0 +Q,HPI_YDH,HUN,2009-Q1,IX,2009,2009,129.175020241349,S,2015,1,A,0 +Q,HPI_YDH,HUN,2009-Q2,IX,2009,2009,128.069036228621,S,2015,1,A,0 +Q,HPI_YDH,HUN,2009-Q3,IX,2009,2009,120.538647006447,S,2015,1,A,0 +Q,HPI_YDH,HUN,2009-Q4,IX,2009,2009,122.981069897426,S,2015,1,A,0 +Q,HPI_YDH,HUN,2010-Q1,IX,2010,2010,120.008425982046,S,2015,1,A,0 +Q,HPI_YDH,HUN,2010-Q2,IX,2010,2010,117.718433849041,S,2015,1,A,0 diff --git a/tests/TimePeriod/test_time_period_formats.py b/tests/TimePeriod/test_time_period_formats.py index 45ec34494..e230b7712 100644 --- a/tests/TimePeriod/test_time_period_formats.py +++ b/tests/TimePeriod/test_time_period_formats.py @@ -14,6 +14,7 @@ import pandas as pd import pytest +from vtlengine import run from vtlengine.DataTypes import TimePeriod from vtlengine.DataTypes._time_checking import check_time_period from vtlengine.DataTypes.TimeHandling import TimePeriodHandler @@ -412,3 +413,87 @@ def test_format_external_multiple_values() -> None: assert ds.data["Id_1"].equals( pd.Series(["2020", "2020M6", "2020Q2"], name="Id_1", dtype="string[pyarrow]") ) + + +# GH-635: cast(TimePeriod, String) uses the configured external representation + + +def _run_cast_tp_to_string(tp_values: List[str], time_period_output_format: str) -> Dataset: + from vtlengine.DataTypes.TimeHandling import TimePeriodConfig + + original = TimePeriodConfig.get_representation() + script = "DS_r <- DS_1[calc Me_2 := cast(Me_1, string)];" + data_structures = { + "datasets": [ + { + "name": "DS_1", + "DataStructure": [ + {"name": "Id_1", "type": "Integer", "role": "Identifier", "nullable": False}, + {"name": "Me_1", "type": "Time_Period", "role": "Measure", "nullable": True}, + ], + } + ] + } + data_df = pd.DataFrame({"Id_1": list(range(1, len(tp_values) + 1)), "Me_1": tp_values}) + try: + result = run( + script=script, + data_structures=data_structures, + datapoints={"DS_1": data_df}, + time_period_output_format=time_period_output_format, + ) + return result["DS_r"] + finally: + TimePeriodConfig.set_representation(original) + + +gh_635_params = [ + pytest.param( + ["2020", "2021", "2022"], + "natural", + ["2020", "2021", "2022"], + id="GH_635_1-annual_natural", + ), + pytest.param( + ["2020", "2021", "2022"], + "vtl", + ["2020", "2021", "2022"], + id="GH_635_2-annual_vtl", + ), + pytest.param( + ["2020M1", "2020M6", "2020M12"], + "natural", + ["2020-01", "2020-06", "2020-12"], + id="GH_635_3-monthly_natural", + ), + pytest.param( + ["2020M1", "2020M6", "2020M12"], + "vtl", + ["2020M1", "2020M6", "2020M12"], + id="GH_635_4-monthly_vtl", + ), + pytest.param( + ["2020Q1", "2020Q4"], + "sdmx_reporting", + ["2020-Q1", "2020-Q4"], + id="GH_635_5-quarterly_sdmx_reporting", + ), + pytest.param( + ["2020", "2020M6", "2020Q3"], + "natural", + ["2020", "2020-06", "2020-Q3"], + id="GH_635_6-mixed_natural", + ), + pytest.param( + ["2020", "2021"], + "sdmx_reporting", + ["2020-A1", "2021-A1"], + id="GH_635_7-annual_sdmx_reporting", + ), +] + + +@pytest.mark.parametrize("tp_values, output_format, expected", gh_635_params) +def test_GH_635(tp_values: List[str], output_format: str, expected: List[str]) -> None: + ds = _run_cast_tp_to_string(tp_values, output_format) + assert list(ds.data["Me_2"]) == expected diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 000000000..e69de29bb