code: def build_time_features_df(dt, conti_year_origin, add_dst_info=True):
      """This function gets a datetime-like vector and creates new columns containing temporal
      features useful for time series analysis and forecasting e.g. year, week of year, etc.
  
      Parameters
      ----------
      dt : array-like (1-dimensional)
          A vector of datetime-like values
      conti_year_origin : `float`
          The origin used for creating continuous time which is in years unit.
      add_dst_info : `bool`, default True
          Determines if daylight saving columns for US and Europe should be added.
      Returns
      -------
      time_features_df : `pandas.DataFrame`
          Dataframe with the following time features.
  
              * "datetime": `datetime.datetime` object, a combination of date and a time
              * "date": `datetime.date` object, date with the format (year, month, day)
              * "year": integer, year of the date e.g. 2018
              * "year_length": integer, number of days in the year e.g. 365 or 366
              * "quarter": integer, quarter of the date, 1, 2, 3, 4
              * "quarter_start": `pandas.DatetimeIndex`, date of beginning of the current quarter
              * "quarter_length": integer, number of days in the quarter, 90/91 for Q1, 91 for Q2, 92 for Q3 and Q4
              * "month": integer, month of the year, January=1, February=2, ..., December=12
              * "month_length": integer, number of days in the month, 28/ 29/ 30/ 31
              * "woy": integer, ISO 8601 week of the year where a week starts from Monday, 1, 2, ..., 53
              * "doy": integer, ordinal day of the year, 1, 2, ..., year_length
              * "doq": integer, ordinal day of the quarter, 1, 2, ..., quarter_length
              * "dom": integer, ordinal day of the month, 1, 2, ..., month_length
              * "dow": integer, day of the week, Monday=1, Tuesday=2, ..., Sunday=7
              * "str_dow": string, day of the week as a string e.g. "1-Mon", "2-Tue", ..., "7-Sun"
              * "str_doy": string, day of the year e.g. "2020-03-20" for March 20, 2020
              * "hour": integer, discrete hours of the datetime, 0, 1, ..., 23
              * "minute": integer, minutes of the datetime, 0, 1, ..., 59
              * "second": integer, seconds of the datetime, 0, 1, ..., 3599
              * "year_month": string, (year, month) e.g. "2020-03" for March 2020
              * "year_woy": string, (year, week of year) e.g. "2020_42" for 42nd week of 2020
              * "month_dom": string, (month, day of month) e.g. "02/20" for February 20th
              * "year_woy_dow": string, (year, week of year, day of week) e.g. "2020_03_6" for Saturday of 3rd week in 2020
              * "woy_dow": string, (week of year, day of week) e.g. "03_6" for Saturday of 3rd week
              * "dow_hr": string, (day of week, hour) e.g. "4_09" for 9am on Thursday
              * "dow_hr_min": string, (day of week, hour, minute) e.g. "4_09_10" for 9:10am on Thursday
              * "tod": float, time of day, continuous, 0.0 to 24.0
              * "tow": float, time of week, continuous, 0.0 to 7.0
              * "tom": float, standardized time of month, continuous, 0.0 to 1.0
              * "toq": float, time of quarter, continuous, 0.0 to 1.0
              * "toy": float, standardized time of year, continuous, 0.0 to 1.0
              * "conti_year": float, year in continuous time, eg 2018.5 means middle of the year 2018
              * "is_weekend": boolean, weekend indicator, True for weekend, else False
              * "dow_grouped": string, Monday-Thursday=1234-MTuWTh, Friday=5-Fri, Saturday=6-Sat, Sunday=7-Sun
              * "ct1": float, linear growth based on conti_year_origin, -infinity to infinity
              * "ct2": float, signed quadratic growth, -infinity to infinity
              * "ct3": float, signed cubic growth, -infinity to infinity
              * "ct_sqrt": float, signed square root growth, -infinity to infinity
              * "ct_root3": float, signed cubic root growth, -infinity to infinity
              * "us_dst": bool, determines if the time inside the daylight saving time of US
                  This column is only generated if ``add_dst_info=True``
              * "eu_dst": bool, determines if the time inside the daylight saving time of Europe. This column is only generated if ``add_dst_info=True``
  
      """
      dt = pd.DatetimeIndex(dt)
      if len(dt) == 0:
          raise ValueError("Length of dt cannot be zero.")
  
      # basic time features
      date = dt.date
      year = dt.year
      year_length = 365.0 + dt.is_leap_year
      quarter = dt.quarter
      month = dt.month
      month_length = dt.days_in_month
  
      # finds first day of quarter
      quarter_start = pd.DatetimeIndex(
          dt.year.map(str)
          + "-"
          + (3 * quarter - 2).map(int).map(str)
          + "-01"
      )
      next_quarter_start = dt + pd.tseries.offsets.QuarterBegin(
          startingMonth=1
      )
      quarter_length = (next_quarter_start - quarter_start).days
      # finds offset from first day of quarter (rounds down to nearest day)
      doq = ((dt - quarter_start) / pd.to_timedelta("1D") + 1).astype(
          int
      )
  
      # week of year, "woy", follows ISO 8601:
      #   - Week 01 is the week with the year's first Thursday in it.
      #   - A week begins with Monday and ends with Sunday.
      # So the week number of the week that overlaps both years, is 1, 52, or 53,
      # depending on whether it has more days in the previous year or new year.
      #   - e.g. Jan 1st, 2018 is Monday. woy of first 8 days = [1, 1, 1, 1, 1, 1, 1, 2]
      #   - e.g. Jan 1st, 2019 is Tuesday. woy of first 8 days = [1, 1, 1, 1, 1, 1, 2, 2]
      #   - e.g. Jan 1st, 2020 is Wednesday. woy of first 8 days = [1, 1, 1, 1, 1, 2, 2, 2]
      #   - e.g. Jan 1st, 2015 is Thursday. woy of first 8 days = [1, 1, 1, 1, 2, 2, 2, 2]
      #   - e.g. Jan 1st, 2021 is Friday. woy of first 8 days = [53, 53, 53, 1, 1, 1, 1, 1]
      #   - e.g. Jan 1st, 2022 is Saturday. woy of first 8 days = [52, 52, 1, 1, 1, 1, 1, 1]
      #   - e.g. Jan 1st, 2023 is Sunday. woy of first 8 days = [52, 1, 1, 1, 1, 1, 1, 1]
      woy = dt.strftime("%V").astype(int)
      doy = dt.dayofyear
      dom = dt.day
      dow = dt.strftime("%u").astype(int)
      str_dow = dt.strftime("%u-%a")  # e.g. 1-Mon, 2-Tue, ..., 7-Sun
      hour = dt.hour
      minute = dt.minute
      second = dt.second
  
      # grouped time feature
      year_quarter = dt.strftime("%Y-") + quarter.astype(
          str
      )  # e.g. 2020-1 for March 2020
      str_doy = dt.strftime(
          "%Y-%m-%d"
      )  # e.g. 2020-03-20 for March 20, 2020
      year_month = dt.strftime("%Y-%m")  # e.g. 2020-03 for March 2020
      month_dom = dt.strftime("%m/%d")  # e.g. 02/20 for February 20th
      year_woy = dt.strftime(
          "%Y_%V"
      )  # e.g. 2020_42 for 42nd week of 2020
      year_woy_dow = dt.strftime(
          "%Y_%V_%u"
      )  # e.g. 2020_03_6 for Saturday of 3rd week in 2020
      woy_dow = dt.strftime(
          "%W_%u"
      )  # e.g. 03_6 for Saturday of 3rd week
      dow_hr = dt.strftime("%u_%H")  # e.g. 4_09 for 9am on Thursday
      dow_hr_min = dt.strftime(
          "%u_%H_%M"
      )  # e.g. 4_09_10 for 9:10am on Thursday
  
      # iso features https://en.wikipedia.org/wiki/ISO_week_date
      # Uses `pd.Index` to avoid overriding the indices in the output df.
      year_iso = pd.Index(dt.isocalendar()["year"])
      year_woy_iso = pd.Index(
          year_iso.astype(str) + "_" + dt.strftime("%V")
      )
      year_woy_dow_iso = pd.Index(
          year_woy_iso + "_" + dt.isocalendar()["day"].astype(str)
      )
  
      # derived time features
      tod = hour + (minute / 60.0) + (second / 3600.0)
      tow = dow - 1 + (tod / 24.0)
      tom = (dom - 1 + (tod / 24.0)) / month_length
      toq = (doq - 1 + (tod / 24.0)) / quarter_length
      # time of year, continuous, 0.0 to 1.0. e.g. Jan 1, 12 am = 0/365, Jan 2, 12 am = 1/365, ...
      # To handle leap years, Feb 28 = 58/365 - 59/365, Feb 29 = 59/365, Mar 1 = 59/365 - 60/365
      # offset term is nonzero only in leap years
      # doy_offset reduces doy by 1 from from Mar 1st (doy > 60)
      doy_offset = (year_length == 366) * 1.0 * (doy > 60)
      # tod_offset sets tod to 0 on Feb 29th (doy == 60)
      tod_offset = 1 - (year_length == 366) * 1.0 * (doy == 60)
      toy = (doy - 1 - doy_offset + (tod / 24.0) * tod_offset) / 365.0
  
      # year of date in continuous time, eg 2018.5 means middle of year 2018
      # this is useful for modeling features that do not care about leap year e.g. environmental variables
      conti_year = year + (doy - 1 + (tod / 24.0)) / year_length
      is_weekend = (
          pd.Series(dow).apply(lambda x: x in [6, 7]).values
      )  # weekend indicator
      # categorical var with levels (Mon-Thu, Fri, Sat, Sun), could help when training data are sparse.
      dow_grouped = (
          pd.Series(str_dow)
          .apply(
              lambda x: "1234-MTuWTh"
              if (x in ["1-Mon", "2-Tue", "3-Wed", "4-Thu"])
              else x
          )
          .values
      )
  
      # growth terms
      ct1 = conti_year - conti_year_origin
      ct2 = signed_pow(ct1, 2)
      ct3 = signed_pow(ct1, 3)
      ct_sqrt = signed_pow(ct1, 1 / 2)
      ct_root3 = signed_pow(ct1, 1 / 3)
  
      # All keys must be added to constants.
      features_dict = {
          cst.TimeFeaturesEnum.datetime.value: dt,
          cst.TimeFeaturesEnum.date.value: date,
          cst.TimeFeaturesEnum.year.value: year,
          cst.TimeFeaturesEnum.year_length.value: year_length,
          cst.TimeFeaturesEnum.quarter.value: quarter,
          cst.TimeFeaturesEnum.quarter_start.value: quarter_start,
          cst.TimeFeaturesEnum.quarter_length.value: quarter_length,
          cst.TimeFeaturesEnum.month.value: month,
          cst.TimeFeaturesEnum.month_length.value: month_length,
          cst.TimeFeaturesEnum.woy.value: woy,
          cst.TimeFeaturesEnum.doy.value: doy,
          cst.TimeFeaturesEnum.doq.value: doq,
          cst.TimeFeaturesEnum.dom.value: dom,
          cst.TimeFeaturesEnum.dow.value: dow,
          cst.TimeFeaturesEnum.str_dow.value: str_dow,
          cst.TimeFeaturesEnum.str_doy.value: str_doy,
          cst.TimeFeaturesEnum.hour.value: hour,
          cst.TimeFeaturesEnum.minute.value: minute,
          cst.TimeFeaturesEnum.second.value: second,
          cst.TimeFeaturesEnum.year_quarter.value: year_quarter,
          cst.TimeFeaturesEnum.year_month.value: year_month,
          cst.TimeFeaturesEnum.year_woy.value: year_woy,
          cst.TimeFeaturesEnum.month_dom.value: month_dom,
          cst.TimeFeaturesEnum.year_woy_dow.value: year_woy_dow,
          cst.TimeFeaturesEnum.woy_dow.value: woy_dow,
          cst.TimeFeaturesEnum.dow_hr.value: dow_hr,
          cst.TimeFeaturesEnum.dow_hr_min.value: dow_hr_min,
          cst.TimeFeaturesEnum.year_iso.value: year_iso,
          cst.TimeFeaturesEnum.year_woy_iso.value: year_woy_iso,
          cst.TimeFeaturesEnum.year_woy_dow_iso.value: year_woy_dow_iso,
          cst.TimeFeaturesEnum.tod.value: tod,
          cst.TimeFeaturesEnum.tow.value: tow,
          cst.TimeFeaturesEnum.tom.value: tom,
          cst.TimeFeaturesEnum.toq.value: toq,
          cst.TimeFeaturesEnum.toy.value: toy,
          cst.TimeFeaturesEnum.conti_year.value: conti_year,
          cst.TimeFeaturesEnum.is_weekend.value: is_weekend,
          cst.TimeFeaturesEnum.dow_grouped.value: dow_grouped,
          cst.TimeFeaturesEnum.ct1.value: ct1,
          cst.TimeFeaturesEnum.ct2.value: ct2,
          cst.TimeFeaturesEnum.ct3.value: ct3,
          cst.TimeFeaturesEnum.ct_sqrt.value: ct_sqrt,
          cst.TimeFeaturesEnum.ct_root3.value: ct_root3,
      }
      df = pd.DataFrame(features_dict)
  
      if add_dst_info:
          df[cst.TimeFeaturesEnum.us_dst.value] = is_dst_fcn(
              "US/Pacific"
          )(df[cst.TimeFeaturesEnum.datetime.value])
  
          df[cst.TimeFeaturesEnum.eu_dst.value] = is_dst_fcn(
              "Europe/London"
          )(df[cst.TimeFeaturesEnum.datetime.value])
  
      return df
  
imports: import math
  from datetime import datetime
  from datetime import timedelta
  import numpy
  import pandas
  import pytz
  from holidays_ext import get_holidays
  from pandas.tseries.frequencies import to_offset
  from scipy.special import expit
  from greykite.common import constants
  from greykite.common.python_utils import split_offset_str
label_desc: Use image node_id 9 for calling a global function with example usage: build_time_features_df(dt, conti_year_origin, add_dst_info) and returns: df