You are here

protected static function DateRecurUtility::createDateFromInput in Recurring Dates Field 3.x

Same name and namespace in other branches
  1. 8.2 src/DateRecurUtility.php \Drupal\date_recur\DateRecurUtility::createDateFromInput()
  2. 3.0.x src/DateRecurUtility.php \Drupal\date_recur\DateRecurUtility::createDateFromInput()
  3. 3.1.x src/DateRecurUtility.php \Drupal\date_recur\DateRecurUtility::createDateFromInput()

Get the smallest or largest date given a granularity and input.

@internal

Parameters

string $granularity: The granularity of the input. E.g 'year', 'month', etc.

string $value: User date input.

\DateTimeZone $timezone: The timezone of the input.

string $end: Either 'start' or 'end' to get a date at the beginning or end of a granularity period.

Return value

\DateTime A date time with the smallest value given granularity and input.

Throws

\InvalidArgumentException When date or granularity results in an invalid data object.

2 calls to DateRecurUtility::createDateFromInput()
DateRecurUtility::createLargestDateFromInput in src/DateRecurUtility.php
Get the largest date given a granularity and input.
DateRecurUtility::createSmallestDateFromInput in src/DateRecurUtility.php
Get the smallest date given a granularity and input.

File

src/DateRecurUtility.php, line 75

Class

DateRecurUtility
Provide standalone utilities.

Namespace

Drupal\date_recur

Code

protected static function createDateFromInput(string $granularity, string $value, \DateTimeZone $timezone, string $end) : \DateTime {
  assert(in_array($end, [
    'start',
    'end',
  ]));
  $start = $end === 'start';
  $granularityFormatsMap = DateRecurGranularityMap::GRANULARITY_DATE_FORMATS;
  $format = $granularityFormatsMap[$granularity];

  // Fill in the month, and day, for Year/Month granularities because if the
  // date we are creating doesnt have a month/day that exists at that time,
  // the date will be created in the future.
  // For example: if today is the 31st day, and the user is searching for
  // 2014-09, where September does not have 31 days, then the created date
  // will roll over to the next month to 2014-10-01.
  if ($granularity === 'year') {
    $format = $granularityFormatsMap['day'];

    // Every year has a month 1 and day 1.
    $value .= '-01-01';
  }
  elseif ($granularity === 'month') {
    $format = $granularityFormatsMap['day'];

    // Every month has a day 1.
    $value .= '-01';
  }

  // PHP fills missing granularity parts with current datetime. Use this
  // object to reconstruct the date at the beginning of the granularity
  // period.
  $knownDate = \DateTime::createFromFormat($format, $value, $timezone);
  if (!$knownDate) {
    throw new \InvalidArgumentException('Unable to create date from input.');
  }
  $granularityComparison = DateRecurGranularityMap::GRANULARITY;
  $granularityInt = $granularityComparison[$granularity];
  $dateParts = [
    'year' => (int) $knownDate
      ->format('Y'),
    'month' => $granularityInt >= 2 ? (int) $knownDate
      ->format('m') : ($start ? 1 : 12),
    'day' => $granularityInt >= 3 ? (int) $knownDate
      ->format('d') : 1,
    'hour' => $granularityInt >= 4 ? (int) $knownDate
      ->format('H') : ($start ? 0 : 23),
    'minute' => $granularityInt >= 5 ? (int) $knownDate
      ->format('i') : ($start ? 0 : 59),
    'second' => $granularityInt >= 6 ? (int) $knownDate
      ->format('s') : ($start ? 0 : 59),
  ];
  $date = DrupalDateTime::createFromArray($dateParts, $knownDate
    ->getTimezone());

  // Getting the last day of a month is a little more complex. Use the created
  // date to get number of days in the month.
  if (!$start && $granularityInt < 3) {
    $dateParts['day'] = $date
      ->format('t');
    $date = DrupalDateTime::createFromArray($dateParts, $date
      ->getTimezone());
  }
  return $date
    ->getPhpDateTime();
}