BBIM 4D: implement human readable duration to read/edit durations.

new IOS Fuzzy Duration Parsing utility
This commit is contained in:
Sigma Dimensions
2023-05-03 16:09:27 +01:00
parent 7d61c292fe
commit 7188d6ea74
5 changed files with 116 additions and 23 deletions
@@ -35,14 +35,15 @@ def timedelta2duration(timedelta):
}
if components["seconds"]:
components["hours"], components["minutes"], components["seconds"] = [
int(i) for i in str(datetime.timedelta(seconds=components["seconds"])).split(":")
int(i)
for i in str(datetime.timedelta(seconds=components["seconds"])).split(":")
]
return isodate.Duration(**components)
def ifc2datetime(element):
if isinstance(element, str) and "P" in element[0:2]: # IfcDuration
duration = isodate.parse_duration(element)
duration = parse_duration(element)
if isinstance(duration, datetime.timedelta):
return timedelta2duration(duration)
return duration
@@ -72,6 +73,38 @@ def ifc2datetime(element):
)
def get_isosplit(s, split):
if split in s:
n, s = s.split(split)
else:
n = 0
return n, s
def readable_ifc_duration(string):
string = string.split("P")[-1]
years, string = get_isosplit(string, "Y")
months, string = get_isosplit(string, "M")
weeks, string = get_isosplit(string, "W")
days, string = get_isosplit(string, "D")
_, string = get_isosplit(string, "T")
hours, string = get_isosplit(string, "H")
minutes, string = get_isosplit(string, "M")
seconds, string = get_isosplit(string, "S")
final_string = ""
final_string += f"{years} y " if years else ""
final_string += f"{months} m " if months else ""
final_string += f"{weeks} w " if weeks else ""
final_string += f"{days} d " if days else ""
final_string += f"{hours} h " if hours else ""
final_string += f"{minutes} m " if minutes else ""
final_string += f"{seconds} s " if seconds else ""
return final_string
def datetime2ifc(dt, ifc_type):
if isinstance(dt, str):
if ifc_type == "IfcDuration":
@@ -89,7 +122,9 @@ def datetime2ifc(dt, ifc_type):
if isinstance(dt, datetime.datetime):
return dt.isoformat()
elif isinstance(dt, datetime.date):
return datetime.datetime.combine(dt, datetime.datetime.min.time()).isoformat()
return datetime.datetime.combine(
dt, datetime.datetime.min.time()
).isoformat()
elif ifc_type == "IfcDate":
if isinstance(dt, datetime.datetime):
return dt.date().isoformat()
@@ -101,10 +136,19 @@ def datetime2ifc(dt, ifc_type):
elif isinstance(dt, datetime.time):
return dt.isoformat()
elif ifc_type == "IfcCalendarDate":
return {"DayComponent": dt.day, "MonthComponent": dt.month, "YearComponent": dt.year}
return {
"DayComponent": dt.day,
"MonthComponent": dt.month,
"YearComponent": dt.year,
}
elif ifc_type == "IfcLocalTime":
# TODO implement timezones
return {"HourComponent": dt.hour, "MinuteComponent": dt.minute, "SecondComponent": dt.second}
return {
"HourComponent": dt.hour,
"MinuteComponent": dt.minute,
"SecondComponent": dt.second,
}
def string_to_date(string):
if not string:
@@ -117,6 +161,7 @@ def string_to_date(string):
except:
return None
def string_to_duration(duration_string):
# TODO support years, months, weeks aswell
days = 0
@@ -135,4 +180,62 @@ def string_to_duration(duration_string):
match = findall(r"(\d+\.?\d*)s", duration_string)
if match:
seconds = float(match[0])
return isodate.duration_isoformat(datetime.timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds))
return isodate.duration_isoformat(
datetime.timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds)
)
def parse_duration(value):
print("parsing duration", value)
if not value:
return None
if isinstance(value, str):
if "P" in value:
try:
return isodate.parse_duration(value)
except:
print("error parsing ISO string duration")
return None
else:
try:
final_string = "P"
value_upper = value.upper()
for char in value_upper:
if char.isdigit():
final_string += char
elif char == "D":
final_string += "D"
if (
"H" in value_upper
or "S" in value_upper
or "MIN" in value_upper
):
final_string += "T"
elif char == "W":
final_string += "W"
elif char == "M":
final_string += "M"
elif char == "Y":
final_string += "Y"
elif char == "H":
final_string = (
final_string[:1] + "T" + final_string[1:]
if "T" not in final_string
else final_string
)
final_string += "H"
elif char == "M":
if "MIN" in value_upper and "T" not in final_string:
final_string = final_string[:1] + "T" + final_string[1:]
final_string += "M"
elif char == "S":
final_string = (
final_string[:1] + "T" + final_string[1:]
if "T" not in final_string
else final_string
)
final_string += "S"
return isodate.parse_duration(final_string)
except:
print("error fuzzy parsing duration")
return None