static fromObject(obj, opts = {}) {
    obj = obj || {};
    const zoneToUse = normalizeZone(opts.zone, Settings.defaultZone);
    if (!zoneToUse.isValid) {
      return DateTime.invalid(unsupportedZone(zoneToUse));
    }

    const loc = Locale.fromObject(opts);
    const normalized = normalizeObject(obj, normalizeUnitWithLocalWeeks);
    const { minDaysInFirstWeek, startOfWeek } = usesLocalWeekValues(normalized, loc);

    const tsNow = Settings.now(),
      offsetProvis = !isUndefined(opts.specificOffset)
        ? opts.specificOffset
        : zoneToUse.offset(tsNow),
      containsOrdinal = !isUndefined(normalized.ordinal),
      containsGregorYear = !isUndefined(normalized.year),
      containsGregorMD = !isUndefined(normalized.month) || !isUndefined(normalized.day),
      containsGregor = containsGregorYear || containsGregorMD,
      definiteWeekDef = normalized.weekYear || normalized.weekNumber;

    // cases:
    // just a weekday -> this week's instance of that weekday, no worries
    // (gregorian data or ordinal) + (weekYear or weekNumber) -> error
    // (gregorian month or day) + ordinal -> error
    // otherwise just use weeks or ordinals or gregorian, depending on what's specified

    if ((containsGregor || containsOrdinal) && definiteWeekDef) {
      throw new ConflictingSpecificationError(
        "Can't mix weekYear/weekNumber units with year/month/day or ordinals"
      );
    }

    if (containsGregorMD && containsOrdinal) {
      throw new ConflictingSpecificationError("Can't mix ordinal dates with month/day");
    }

    const useWeekData = definiteWeekDef || (normalized.weekday && !containsGregor);

    // configure ourselves to deal with gregorian dates or week stuff
    let units,
      defaultValues,
      objNow = tsToObj(tsNow, offsetProvis);
    if (useWeekData) {
      units = orderedWeekUnits;
      defaultValues = defaultWeekUnitValues;
      objNow = gregorianToWeek(objNow, minDaysInFirstWeek, startOfWeek);
    } else if (containsOrdinal) {
      units = orderedOrdinalUnits;
      defaultValues = defaultOrdinalUnitValues;
      objNow = gregorianToOrdinal(objNow);
    } else {
      units = orderedUnits;
      defaultValues = defaultUnitValues;
    }

    // set default values for missing stuff
    let foundFirst = false;
    for (const u of units) {
      const v = normalized[u];
      if (!isUndefined(v)) {
        foundFirst = true;
      } else if (foundFirst) {
        normalized[u] = defaultValues[u];
      } else {
        normalized[u] = objNow[u];
      }
    }

    // make sure the values we have are in range
    const higherOrderInvalid = useWeekData
        ? hasInvalidWeekData(normalized, minDaysInFirstWeek, startOfWeek)
        : containsOrdinal
        ? hasInvalidOrdinalData(normalized)
        : hasInvalidGregorianData(normalized),
      invalid = higherOrderInvalid || hasInvalidTimeData(normalized);

    if (invalid) {
      return DateTime.invalid(invalid);
    }

    // compute the actual time
    const gregorian = useWeekData
        ? weekToGregorian(normalized, minDaysInFirstWeek, startOfWeek)
        : containsOrdinal
        ? ordinalToGregorian(normalized)
        : normalized,
      [tsFinal, offsetFinal] = objToTS(gregorian, offsetProvis, zoneToUse),
      inst = new DateTime({
        ts: tsFinal,
        zone: zoneToUse,
        o: offsetFinal,
        loc,
      });

    // gregorian data + weekday serves only to validate
    if (normalized.weekday && containsGregor && obj.weekday !== inst.weekday) {
      return DateTime.invalid(
        "mismatched weekday",
        `you can't specify both a weekday of ${normalized.weekday} and a date of ${inst.toISO()}`
      );
    }

    if (!inst.isValid) {
      return DateTime.invalid(inst.invalid);
    }

    return inst;
  }
Create a DateTime from a JavaScript object with keys like 'year' and 'hour' with reasonable defaults.
@param {Object} obj - the object to create the DateTime from
@param {number} obj.year - a year, such as 1987
@param {number} obj.month - a month, 1-12
@param {number} obj.day - a day of the month, 1-31, depending on the month
@param {number} obj.ordinal - day of the year, 1-365 or 366
@param {number} obj.weekYear - an ISO week year
@param {number} obj.weekNumber - an ISO week number, between 1 and 52 or 53, depending on the year
@param {number} obj.weekday - an ISO weekday, 1-7, where 1 is Monday and 7 is Sunday
@param {number} obj.localWeekYear - a week year, according to the locale
@param {number} obj.localWeekNumber - a week number, between 1 and 52 or 53, depending on the year, according to the locale
@param {number} obj.localWeekday - a weekday, 1-7, where 1 is the first and 7 is the last day of the week, according to the locale
@param {number} obj.hour - hour of the day, 0-23
@param {number} obj.minute - minute of the hour, 0-59
@param {number} obj.second - second of the minute, 0-59
@param {number} obj.millisecond - millisecond of the second, 0-999
@param {Object} opts - options for creating this DateTime
@param {string|Zone} [opts.zone='local'] - interpret the numbers in the context of a particular zone. Can take any value taken as the first argument to setZone()
@param {string} [opts.locale='system\'s locale'] - a locale to set on the resulting DateTime instance
@param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance
@param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance
@param {string} opts.weekSettings - the week settings to set on the resulting DateTime instance
@example DateTime.fromObject({ year: 1982, month: 5, day: 25}).toISODate() //=> '1982-05-25'
@example DateTime.fromObject({ year: 1982 }).toISODate() //=> '1982-01-01'
@example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }) //~> today at 10:26:06
@example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'utc' }),
@example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'local' })
@example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'America/New_York' })
@example DateTime.fromObject({ weekYear: 2016, weekNumber: 2, weekday: 3 }).toISODate() //=> '2016-01-13'
@example DateTime.fromObject({ localWeekYear: 2022, localWeekNumber: 1, localWeekday: 1 }, { locale: "en-US" }).toISODate() //=> '2021-12-26'
@return {DateTime}