diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_time.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_time.py index 6d867155b0..c9c76dfee2 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_time.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/edit_work_time.py @@ -17,6 +17,7 @@ # along with IfcOpenShell. If not, see . import ifcopenshell.util.date +from ifcopenshell.util.data import WorkTimeDatesInterface class Usecase: @@ -54,9 +55,10 @@ class Usecase: self.settings = {"work_time": work_time, "attributes": attributes or {}} def execute(self): + work_time_dates = WorkTimeDatesInterface(self.settings["work_time"]) for name, value in self.settings["attributes"].items(): - if value and name in ("Start", "Finish", "StartDate", "FinishDate"): + if name in ("Start", "Finish", "StartDate", "FinishDate"): value = ifcopenshell.util.date.datetime2ifc(value, "IfcDate") - if self.file.schema == "IFC4X3" and name in ("Start", "Finish"): - name += "Date" - setattr(self.settings["work_time"], name, value) + setattr(work_time_dates, name, value) + else: + setattr(self.settings["work_time"], name, value) diff --git a/src/ifcopenshell-python/ifcopenshell/util/data.py b/src/ifcopenshell-python/ifcopenshell/util/data.py index a66ea80252..e6761edd5d 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/data.py +++ b/src/ifcopenshell-python/ifcopenshell/util/data.py @@ -93,3 +93,37 @@ class Clipping: second_operand = ifc_file.createIfcHalfSpaceSolid(plane, False) return ifc_file.createIfcBooleanClippingResult("DIFFERENCE", first_operand, second_operand) + + +class WorkTimeDatesInterface: + def __init__(self, work_time: ifcopenshell.entity_instance): + """Utility class for IfcWorkTime dates allowing refer + to it's dates as `.Start`/`.Finish` or `.StartDate`/`.FinishDate` + regardless of the schema version + """ + if hasattr(work_time, "StartDate"): # since IFC4X3 + self.start_attr, self.finish_attr = "StartDate", "FinishDate" + else: + self.start_attr, self.finish_attr = "Start", "Finish" + + self.work_time = work_time + + @property + def Start(self): + return getattr(self.work_time, self.start_attr) + + @Start.setter + def Start(self, value): + return setattr(self.work_time, self.start_attr, value) + + StartDate = Start + + @property + def Finish(self): + return getattr(self.work_time, self.finish_attr) + + @Finish.setter + def Finish(self, value): + return setattr(self.work_time, self.finish_attr, value) + + FinishDate = Finish diff --git a/src/ifcopenshell-python/ifcopenshell/util/sequence.py b/src/ifcopenshell-python/ifcopenshell/util/sequence.py index ebdedb5890..f450dbf5ed 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/sequence.py +++ b/src/ifcopenshell-python/ifcopenshell/util/sequence.py @@ -18,8 +18,10 @@ import datetime import ifcopenshell.util.date +from ifcopenshell.util.data import WorkTimeDatesInterface from math import floor from functools import lru_cache +from collections import namedtuple def derive_date(task, attribute_name, date=None, is_earliest=False, is_latest=False): @@ -180,14 +182,15 @@ def is_day_in_work_time(day, work_time): is_day_in_work_time = True if isinstance(day, datetime.datetime): day = datetime.date(day.year, day.month, day.day) - if work_time.Start: - start = ifcopenshell.util.date.ifc2datetime(work_time.Start) + work_time_dates = WorkTimeDatesInterface(work_time) + if work_time_dates.Start: + start = ifcopenshell.util.date.ifc2datetime(work_time_dates.Start) if day > start: is_day_in_work_time = True else: is_day_in_work_time = False - if work_time.Finish: - finish = ifcopenshell.util.date.ifc2datetime(work_time.Finish) + if work_time_dates.Finish: + finish = ifcopenshell.util.date.ifc2datetime(work_time_dates.Finish) if day < finish: is_day_in_work_time = True else: @@ -204,16 +207,17 @@ def is_work_time_applicable_to_day(work_time, day): if isinstance(day, datetime.datetime): day = datetime.date(day.year, day.month, day.day) recurrence = work_time.RecurrencePattern + work_time_dates = WorkTimeDatesInterface(work_time) if recurrence.RecurrenceType == "DAILY": if not recurrence.Interval and not recurrence.Occurrences: return True - if not work_time.Start: + if not work_time_dates.Start: return False return False # TODO elif recurrence.RecurrenceType == "WEEKLY": if not recurrence.Interval and not recurrence.Occurrences: return (day.weekday() + 1) in recurrence.WeekdayComponent - if not work_time.Start: + if not work_time_dates.Start: return False return False # TODO elif recurrence.RecurrenceType == "MONTHLY_BY_DAY_OF_MONTH": diff --git a/src/ifcopenshell-python/test/api/sequence/test_edit_work_time.py b/src/ifcopenshell-python/test/api/sequence/test_edit_work_time.py index 4ce8d3389b..d91abe2a31 100644 --- a/src/ifcopenshell-python/test/api/sequence/test_edit_work_time.py +++ b/src/ifcopenshell-python/test/api/sequence/test_edit_work_time.py @@ -19,6 +19,7 @@ import datetime import test.bootstrap import ifcopenshell.api +from ifcopenshell.util.data import WorkTimeDatesInterface class TestEditWorkTime(test.bootstrap.IFC4): @@ -34,12 +35,13 @@ class TestEditWorkTime(test.bootstrap.IFC4): "Finish": datetime.datetime(2020, 2, 1), } ifcopenshell.api.run("sequence.edit_work_time", self.file, work_time=work_time, attributes=attributes) + worktime_dates = WorkTimeDatesInterface(work_time) assert work_time.Name == attributes["Name"] assert work_time.DataOrigin == attributes["DataOrigin"] assert work_time.UserDefinedDataOrigin == attributes["UserDefinedDataOrigin"] assert work_time.RecurrencePattern == attributes["RecurrencePattern"] - assert work_time.Start == "2020-01-01" - assert work_time.Finish == "2020-02-01" + assert worktime_dates.Start == "2020-01-01" + assert worktime_dates.Finish == "2020-02-01" class TestEditWorkTimeIFC4X3(test.bootstrap.IFC4X3): @@ -63,20 +65,4 @@ class TestEditWorkTimeIFC4X3(test.bootstrap.IFC4X3): assert work_time.FinishDate == "2020-02-01" def test_ifc4_code_to_work_in_ifc4x3(self): - work_time = self.file.createIfcWorkTime() - recurrence_pattern = self.file.createIfcRecurrencePattern() - attributes = { - "Name": "Test", - "DataOrigin": "USERDEFINED", - "UserDefinedDataOrigin": "Custom", - "RecurrencePattern": recurrence_pattern, - "Start": datetime.datetime(2020, 1, 1), - "Finish": datetime.datetime(2020, 2, 1), - } - ifcopenshell.api.run("sequence.edit_work_time", self.file, work_time=work_time, attributes=attributes) - assert work_time.Name == attributes["Name"] - assert work_time.DataOrigin == attributes["DataOrigin"] - assert work_time.UserDefinedDataOrigin == attributes["UserDefinedDataOrigin"] - assert work_time.RecurrencePattern == attributes["RecurrencePattern"] - assert work_time.StartDate == "2020-01-01" - assert work_time.FinishDate == "2020-02-01" + TestEditWorkTime.test_run(self)