Esempio n. 1
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $output->writeln('Starting...');
     $output->writeln('Getting disrupted lines...');
     $lines = $this->getContainer()->get('console.services.line')->findAllDisrupted();
     $count = $lines->getResultCount();
     $output->writeln($count . ' disrupted lines');
     $now = new \DateTimeImmutable();
     if ($count > 0) {
         $lines = $lines->getDomainModels();
         $day = (int) $now->format('N');
         $hour = (int) $now->format('H');
         foreach ($lines as $line) {
             $output->writeln('Getting relevant subscriptions for ' . $line->getName() . ' on day ' . $day . ', hour ' . $hour . '...');
             $subscriptions = $this->getContainer()->get('console.services.subscription')->findAllForLineAndHour($line, $day, $hour);
             $scount = $subscriptions->getResultCount();
             $output->writeln($scount . ' subscriptions found');
             if ($scount > 0) {
                 $title = $line->getStatusSummary();
                 $this->notify($line, $title, $subscriptions->getDomainModels());
                 $output->writeln('Notified ' . $line->getName() . ': ' . $title);
                 // if we sent out some notifications, sleep for 2 seconds before sending more
                 sleep(2);
             }
         }
     }
     $output->writeln('Done');
 }
 public function testResponseToPropertiesTimestampValue()
 {
     $date = new \DateTimeImmutable();
     $data = ['foo' => ['timestampValue' => $date->format(self::DATE_FORMAT)]];
     $res = $this->mapper->responseToEntityProperties($data)['properties'];
     $this->assertInstanceOf(\DateTimeImmutable::class, $res['foo']);
     $this->assertEquals($date->format('c'), $res['foo']->format('c'));
 }
Esempio n. 3
0
 public function toString() : string
 {
     if ($this->expiry instanceof \DateTimeImmutable) {
         $rawToken = $this->token . self::DELIMITER . $this->expiry->format(self::DATE_FORMAT);
     } else {
         $rawToken = $this->token;
     }
     return base64_encode($rawToken);
 }
 /**
  * @test
  */
 function it_creates_a_new_message_from_array_and_fqcn()
 {
     $uuid = Uuid::uuid4();
     $createdAt = new \DateTimeImmutable();
     $command = $this->messageFactory->createMessageFromArray(DoSomething::class, ['uuid' => $uuid->toString(), 'version' => 1, 'payload' => ['command' => 'payload'], 'metadata' => ['command' => 'metadata'], 'created_at' => $createdAt->format(\DateTime::ISO8601)]);
     $this->assertEquals(DoSomething::class, $command->messageName());
     $this->assertEquals($uuid->toString(), $command->uuid()->toString());
     $this->assertEquals($createdAt->format(\DateTime::ISO8601), $command->createdAt()->format(\DateTime::ISO8601));
     $this->assertEquals(1, $command->version());
     $this->assertEquals(['command' => 'payload'], $command->payload());
     $this->assertEquals(['command' => 'metadata'], $command->metadata());
 }
Esempio n. 5
0
 private function calculateCalendarMonths()
 {
     $months = ((int) $this->date->format('Y') - (int) $this->baseDate->format('Y')) * 12;
     $months += (int) $this->date->format('m') - (int) $this->baseDate->format('m');
     if ($this->date > $this->baseDate) {
         return $months + ($this->date->format('d') < $this->baseDate->format('d') ? -1 : 0);
     } else {
         if ($this->date < $this->baseDate) {
             return $months + ($this->date->format('d') > $this->baseDate->format('d') ? 1 : 0);
         }
     }
     return $months;
 }
Esempio n. 6
0
 public function hourAction()
 {
     //Define your file path based on the cache one
     $filename = $this->container->getParameter('kernel.cache_dir') . '/timestamps/hour.txt';
     $data = @file_get_contents($filename);
     $now = new \DateTimeImmutable();
     $min = (int) $now->format('i');
     $timestamp = $now->getTimestamp();
     $last = (int) $data ?? 0;
     $diff = $timestamp - $last;
     // can only run in the first 5 mins of an hour,
     // and cannot run again within 10 mins
     $withinMin = $min <= 5;
     if ($withinMin && $diff > 10 * 60) {
         $command = new StatusHourlyCommand();
         $command->setContainer($this->container);
         $input = new ArrayInput([]);
         $output = new NullOutput();
         $resultCode = $command->run($input, $output);
         //Create your own folder in the cache directory
         $fs = new Filesystem();
         $fs->mkdir(dirname($filename));
         file_put_contents($filename, $timestamp);
     } else {
         $resultCode = 1;
     }
     return new JsonResponse((object) ['status' => $resultCode, 'diff' => $diff, 'inWindow' => $withinMin]);
 }
 public function testTransformDateTimeImmutable()
 {
     $transformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'America/New_York');
     $input = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York');
     $output = $input->format('U');
     $input = $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));
     $this->assertEquals($output, $transformer->transform($input));
 }
Esempio n. 8
0
 /**
  * @param Response $response
  * @param string $cookieName
  * @param string $cookieValue
  * @return Response
  */
 public static function addCookie(Response $response, $cookieName, $cookieValue)
 {
     $expirationMinutes = 10;
     $expiry = new \DateTimeImmutable('now + ' . $expirationMinutes . 'minutes');
     $cookie = urlencode($cookieName) . '=' . urlencode($cookieValue) . '; expires=' . $expiry->format(\DateTime::COOKIE) . '; Max-Age=' . $expirationMinutes * 60 . '; path=/; secure; httponly';
     $response = $response->withAddedHeader('Set-Cookie', $cookie);
     return $response;
 }
Esempio n. 9
0
 /**
  * Get the string value of the body in this Header.
  *
  * This is not necessarily RFC 2822 compliant since folding white space will
  * not be added at this stage (see {@link toString()} for that).
  *
  * @see toString()
  *
  * @return string
  */
 public function getFieldBody()
 {
     if (!$this->getCachedValue()) {
         if (isset($this->dateTime)) {
             $this->setCachedValue($this->dateTime->format(DateTime::RFC2822));
         }
     }
     return $this->getCachedValue();
 }
Esempio n. 10
0
 public function postUp(Schema $schema)
 {
     $lineData = [['bakerloo-line', 'bakerloo', 'Bakerloo', 'Bakerloo Line'], ['central-line', 'central', 'Central', 'Central Line'], ['circle-line', 'circle', 'Circle', 'Circle Line'], ['district-line', 'district', 'District', 'District Line'], ['hammersmith-city-line', 'hammersmith-city', 'Hammersmith & City', 'Hammersmith & City Line'], ['jubilee-line', 'jubilee', 'Jubilee', 'Jubilee Line'], ['metropolitan-line', 'metropolitan', 'Metropolitan', 'Metropolitan Line'], ['northern-line', 'northern', 'Northern', 'Northern Line'], ['piccadilly-line', 'piccadilly', 'Piccadilly', 'Piccadilly Line'], ['victoria-line', 'victoria', 'Victoria', 'Victoria Line'], ['waterloo-city-line', 'waterloo-city', 'Waterloo & City', 'Waterloo & City Line'], ['dlr', 'dlr', 'DLR', 'DLR'], ['london-overground', 'london-overground', 'London Overground', 'London Overground'], ['tfl-rail', 'tfl-rail', 'TFL Rail', 'TFL Rail']];
     $now = new \DateTimeImmutable();
     $iso = $now->format('c');
     foreach ($lineData as $i => $line) {
         $this->addSql('INSERT INTO `tube_lines` (url_key, tfl_key, short_name, name, display_order, created_at, updated_at) VALUES (?,?,?,?,?,?,?)', [$line[0], $line[1], $line[2], $line[3], $i + 1, $iso, $iso]);
     }
 }
 /**
  * @param int $fromTs
  * @param int $toTs
  *
  * @return \Generator
  */
 public static function generate($fromTs, $toTs)
 {
     $firstDay = new \DateTimeImmutable(date('Y-m-d', $fromTs));
     $lastDay = new \DateTimeImmutable(date('Y-m-d', $toTs));
     $cursor = new \DateTime($lastDay->format('Y-m-d'));
     while ($cursor >= $firstDay) {
         (yield $cursor->format('Y-m-d'));
         $cursor->sub(new \DateInterval('P1D'));
     }
 }
 public function testDisplayValueForDateTimeImmutable()
 {
     if (PHP_VERSION_ID < 50500) {
         $this->markTestSkipped('\\DateTimeImmutable was introduced in PHP 5.5');
     }
     $now = new \DateTimeImmutable();
     $column = new DateTimeColumn();
     $column->setFormat('Y-m-d H:i:s');
     $this->assertEquals($now->format('Y-m-d H:i:s'), $column->getDisplayedValue($now));
 }
Esempio n. 13
0
 /**
  * Builds the cookie into a HTTP response header.
  *
  * @return string
  */
 public function build() : string
 {
     $str = urlencode($this->name()) . '=' . urlencode($this->value());
     if ($this->expiration) {
         $str .= '; expires=' . $this->expiration->format(\DateTime::COOKIE);
     }
     if (isset($this->attributes[CookieInterface::ATTR_PATH])) {
         $str .= '; path=' . $this->attributes[CookieInterface::ATTR_PATH];
     }
     if (isset($this->attributes[CookieInterface::ATTR_DOMAIN])) {
         $str .= '; domain=' . $this->attributes[CookieInterface::ATTR_DOMAIN];
     }
     if (isset($this->attributes[CookieInterface::ATTR_SECURE]) && $this->attributes[CookieInterface::ATTR_SECURE] === true) {
         $str .= '; secure';
     }
     if (isset($this->attributes[CookieInterface::ATTR_HTTP]) && $this->attributes[CookieInterface::ATTR_HTTP] === true) {
         $str .= '; httponly';
     }
     return $str;
 }
 public function testTransformDateTimeImmutable()
 {
     if (PHP_VERSION_ID < 50500) {
         $this->markTestSkipped('DateTimeImmutable was introduced in PHP 5.5.0');
     }
     $transformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'America/New_York');
     $input = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York');
     $output = $input->format('U');
     $input = $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));
     $this->assertEquals($output, $transformer->transform($input));
 }
 /**
  * @param Channel $channel
  * @param \DateTimeImmutable $specifiedDate
  * @return array
  */
 public function getListingsOf(Channel $channel, \DateTimeImmutable $specifiedDate)
 {
     $criteria = array('channel' => array('builder' => function ($alias) {
         return sprintf("%s.channel", $alias);
     }, 'value' => $channel), 'programDate' => array('builder' => function ($alias) {
         return sprintf("DATE(%s.programDate)", $alias);
     }, 'value' => $specifiedDate->format('Y-m-d')), 'orderBy' => array('builder' => function ($alias) {
         return sprintf("%s.programDate", $alias);
     }, 'value' => 'ASC'));
     return $this->entityManager->findBy(Listing::class, $criteria);
 }
Esempio n. 16
0
 protected function getFormattedDateTime(Episode $episode)
 {
     if (!$episode->firstAired) {
         return 'N/A';
     }
     $date_time = $episode->firstAired->format('D - d/m/Y');
     $today = new \DateTimeImmutable();
     if ($episode->firstAired->format('d/m/y') === $today->format('d/m/y')) {
         $date_time = '<info>' . $date_time . '</info>';
     }
     return $date_time;
 }
Esempio n. 17
0
 public function test_updating_metadata()
 {
     $mao = $this->registry->getMAO("test");
     $id = MetadataId::generate();
     $mao->save(new Metadata($id, "test", []));
     $metadata = $mao->getBy(['id' => (string) $id]);
     $updatedDate = new \DateTimeImmutable();
     $metadata->without_default = $updatedDate;
     $mao->save($metadata);
     $metadata = $mao->getBy(['id' => (string) $id]);
     $this->assertEquals($updatedDate->format('U'), $metadata->without_default->format('U'));
 }
 /**
  * @test
  */
 public function it_publishes_messages()
 {
     $now = new \DateTimeImmutable('now', new \DateTimeZone('UTC'));
     $producer = $this->prophesize(Producer::class);
     $producer->publish(['message_name' => 'test-message', 'uuid' => 'ccefedef-85e1-4fd0-b247-ed13d378b050', 'version' => 1, 'payload' => [], 'metadata' => [], 'created_at' => $now->format('Y-m-d\\TH:i:s.u')], 'test-message', Constants::AMQP_NOPARAM, ['app_id' => 'test_app', 'timestamp' => $now->getTimestamp(), 'type' => 'test-message'])->shouldBeCalled();
     $message = $this->prophesize(Message::class);
     $message->createdAt()->willReturn($now)->shouldBeCalled();
     $message->messageName()->willReturn('test-message')->shouldBeCalled();
     $messageConverter = $this->prophesize(MessageConverter::class);
     $messageConverter->convertToArray($message)->willReturn(['message_name' => 'test-message', 'uuid' => 'ccefedef-85e1-4fd0-b247-ed13d378b050', 'version' => 1, 'payload' => [], 'metadata' => [], 'created_at' => $now])->shouldBeCalled();
     $messageProducer = new AmqpMessageProducer($producer->reveal(), $messageConverter->reveal(), 'test_app');
     $messageProducer($message->reveal());
 }
Esempio n. 19
0
 /**
  * Convert a UNIX timestamp to a DOS timestamp.
  *
  * @param \DateTimeImmutable $date
  * @return string DOS timestamp
  */
 public static function dostime(\DateTimeImmutable $date)
 {
     // get date array for timestamp
     $d = getdate($date->format('U'));
     // set lower-bound on dates
     if ($d['year'] < 1980) {
         $d = array('year' => 1980, 'mon' => 1, 'mday' => 1, 'hours' => 0, 'minutes' => 0, 'seconds' => 0);
     }
     // remove extra years from 1980
     $d['year'] -= 1980;
     // return date string
     return $d['year'] << 25 | $d['mon'] << 21 | $d['mday'] << 16 | $d['hours'] << 11 | $d['minutes'] << 5 | $d['seconds'] >> 1;
 }
Esempio n. 20
0
 /**
  * {@inheritdoc}
  */
 public function normalize($data)
 {
     if (is_string($data)) {
         try {
             $data = new \DateTimeImmutable($data);
         } catch (\Exception $e) {
             throw new NormalizationException('The value must be a date');
         }
     }
     if (!$data instanceof \DateTimeInterface) {
         throw new NormalizationException('The value must be an instance of \\DateTimeInterface');
     }
     return $data->format($this->format);
 }
Esempio n. 21
0
 /**
  * @param string $calendarId
  * @param string $summary
  * @param \DateTimeImmutable $start
  * @param \DateTimeImmutable $end
  * @param null|string $description
  * @return string Event ID in calendar
  */
 public function insertEvent($calendarId, $summary, \DateTimeImmutable $start, \DateTimeImmutable $end, $description = null)
 {
     $event = new \Google_Service_Calendar_Event();
     $event->setSummary($summary);
     $eventStart = new \Google_Service_Calendar_EventDateTime();
     $eventStart->setDateTime($start->format('c'));
     $event->setStart($eventStart);
     $eventEnd = new \Google_Service_Calendar_EventDateTime();
     $eventEnd->setDateTime($end->format('c'));
     $event->setEnd($eventEnd);
     $event->setDescription($description);
     $createdEvent = $this->service->events->insert($calendarId, $event);
     return $createdEvent->id;
 }
Esempio n. 22
0
 public static function getPeriodDays(\DateTimeImmutable $dateStart, \DateTimeImmutable $dateEnd, $excludeStartDate = NULL)
 {
     $days = [];
     if ($dateStart->format("Y-m-d") === $dateEnd->format("Y-m-d")) {
         $days[] = $dateStart->format("Y-m-d");
     } else {
         $interval = new \DateInterval('P1D');
         $dateRange = new \DatePeriod($dateStart, $interval, $dateEnd->add(new \DateInterval('P1D')), $excludeStartDate);
         foreach ($dateRange as $day) {
             $days[] = $day->format("Y-m-d");
         }
     }
     return $days;
 }
Esempio n. 23
0
 protected function getFormattedDateTime(Episode $episode)
 {
     if (!$episode->firstAired) {
         return 'N/A';
     }
     $today = new \DateTimeImmutable();
     $format = 'red';
     // If the episode comes out today, then make it green.
     if ($episode->firstAired->format('d/m/y') === $today->format('d/m/y')) {
         $format = 'info';
     } elseif ($episode->firstAired->getTimestamp() > $today->getTimestamp()) {
         // Episode in the future.
         $format = 'comment';
     }
     $date_time = $episode->firstAired->format('D - d/m/Y');
     return $format ? "<{$format}>{$date_time}</{$format}>" : $date_time;
 }
Esempio n. 24
0
 public function it_can_retrieve_a_user(\PDOStatement $statement)
 {
     $tokenUuid = Uuid::uuid4();
     $userUuid = Uuid::uuid4();
     $expires = new \DateTimeImmutable('+42 seconds');
     $tokenRow = ['token_uuid' => $tokenUuid->getBytes(), 'pass_code' => bin2hex(random_bytes(20)), 'user_uuid' => $userUuid->getBytes(), 'expires' => $expires->format('Y-m-d H:i:s')];
     $this->pdo->prepare(new Argument\Token\StringContainsToken('FROM tokens'))->willReturn($statement);
     $statement->execute(['token_uuid' => $tokenUuid->getBytes()])->shouldBeCalled();
     $statement->rowCount()->willReturn(1);
     $statement->fetch(\PDO::FETCH_ASSOC)->willReturn($tokenRow);
     $token = $this->getByUuid($tokenUuid);
     $token->shouldHaveType(Token::class);
     $token->getUuid()->equals($tokenUuid)->shouldReturn(true);
     $token->getPassCode()->shouldReturn($tokenRow['pass_code']);
     $token->getUserUuid()->equals($userUuid)->shouldReturn(true);
     $token->getExpires()->format('Y-m-d H:i:s')->shouldReturn($tokenRow['expires']);
 }
Esempio n. 25
0
 public function testCallsMethodOnContainedObjectsWithMultipleArgumentsReturnsArray()
 {
     $collection = $this->getTestDuCollection(User::class);
     $date = new \DateTimeImmutable();
     $action = 'login';
     $expectedString = sprintf('Performed action %s on %s', $action, $date->format('c'));
     $collection->add(new User());
     $collection->add(new User());
     $collection->add(new User());
     $values = $collection->performAction($date, $action);
     if (!is_array($values) || count($values) !== 3) {
         $this->fail(sprintf('%s expected returned values to be array of size 3, but got %s', __METHOD__, gettype($values)));
     }
     foreach ($values as $value) {
         $this->assertSame($expectedString, $value);
     }
 }
Esempio n. 26
0
 public function testBinEmptyDeletionCriteria()
 {
     $todayOb = new \DateTimeImmutable("today");
     $today = $todayOb->format("c");
     $yesterday = $todayOb->modify("-1 days")->format("c");
     $dayBefore = $todayOb->modify("-2 days")->format("c");
     $tomorrow = $todayOb->modify("+1 days")->format("c");
     $r = new Recycle($this->storageDir);
     $inputItems = [$tomorrow, $today, $yesterday, $dayBefore, "somerandomfile"];
     $toDelete = $this->invokeMethod($r, "generateDeletionList", ["keepDays" => 0, "items" => $inputItems]);
     static::assertEquals([$tomorrow, $today, $yesterday, $dayBefore], $toDelete);
     $toDelete = $this->invokeMethod($r, "generateDeletionList", ["keepDays" => 1, "items" => $inputItems]);
     static::assertEquals([$tomorrow, $yesterday, $dayBefore], $toDelete);
     $toDelete = $this->invokeMethod($r, "generateDeletionList", ["keepDays" => 2, "items" => $inputItems]);
     static::assertEquals([$tomorrow, $dayBefore], $toDelete);
     $toDelete = $this->invokeMethod($r, "generateDeletionList", ["keepDays" => 3, "items" => $inputItems]);
     static::assertEquals([$tomorrow], $toDelete);
 }
Esempio n. 27
0
 /**
  * Move a file or directory to the recycle bin.
  *
  * @param $path
  * @return string The path that $path was renamed to.
  * @throws \Exception
  */
 public function moveToBin($path)
 {
     $path = Path::canonicalize($path);
     $this->pathSafetyCheck($path);
     $date = new \DateTimeImmutable("today");
     $dateStr = $date->format("c");
     $unique = (string) microtime(true) . '-' . (string) rand(0, 100000);
     $basename = basename($path);
     $todayDir = $this->storageDirectory . $dateStr;
     $finalRestingPlaceDir = "{$todayDir}/{$unique}";
     $finalRestingPlace = "{$finalRestingPlaceDir}/{$basename}";
     $this->ensureDirUsable($this->storageDirectory);
     $this->ensureDirUsable($todayDir);
     $this->ensureDirUsable($finalRestingPlaceDir);
     // Would use PHP's rename but... it doesn't always work
     // when moving a directory to another device.
     exec("mv {$path} {$finalRestingPlace}");
     return $finalRestingPlace;
 }
 /**
  * Return the week dates (first day, last day, list of days) given options passed
  *
  * @param array $options with the following keys :
  * - date_day : \DateTimeInterface of the day of reference
  * - enable_next_week : boolean - True if the week to return is the next following
  *    the week containing the day of reference
  * - days_ofweek_off [optional] : Day::constants[] list of days generally off in the week.
  * - dates_off [optional] : \DateTime[] list of dates off in the week
  *
  * @return array associative array with the following keys :
  * - first_day : \DateTimeImmutable of the first day of the week (the monday)
  * - last_day : \DateTimeImmutable of the last day of the week (the friday)
  * - days : \DateTimeImmutable[] index array of days in the week that take in account
  *  the closed days passed in options
  */
 public function getWeekDates($options)
 {
     $options = $this->weekMealResolver->resolve($options);
     if (true === $options['enable_next_week']) {
         $firstDayFormat = ' next monday';
         $lastDayFormat = ' next friday';
     } else {
         $firstDayFormat = ' monday this week';
         $lastDayFormat = ' friday this week';
     }
     $firstDay = new \DateTimeImmutable($options['date_day']->format('Y-m-d') . $firstDayFormat);
     $lastDay = new \DateTimeImmutable($firstDay->format('Y-m-d') . $lastDayFormat);
     $periode = new Period($firstDay, $lastDay);
     $days = [];
     foreach ($periode->getDayIterator() as $date) {
         if (false === \in_array(Day::getWeekDayFrom($date), $options['days_ofweek_off']) && false === \in_array($date, $options['dates_off'])) {
             $days[] = $date;
         }
     }
     return array('first_day' => $firstDay, 'last_day' => $lastDay, 'days' => $days);
 }
Esempio n. 29
0
 public function testCanUpdateTask()
 {
     $date = new \DateTimeImmutable();
     $string = 'this is a description ' . microtime(true);
     $statement = $this->pdo->prepare('INSERT INTO task (description, dueDate) values (:description, :dueDate)');
     $statement->execute(array(':description' => $string, ':dueDate' => $date->format('Y-m-d H:i:s')));
     $id = $this->pdo->lastInsertId();
     $this->assertNotNull($id);
     $this->task->addSpecification(new TaskFutureDueDate());
     $taskExistSpecification = new TaskExists();
     $taskExistSpecification->setRepository($this->repository);
     $this->task->addSpecification($taskExistSpecification);
     $updateString = 'another description ' . microtime(true);
     $this->task->setId(new Id($id));
     $this->task->setDescription(new TaskDescription($updateString));
     $this->task->setDueDate($date);
     $this->task->setStatus(new Status(0));
     $this->task->setDeleted(new Status(1));
     $deletedDate = $this->task->getDeleteDate();
     $this->assertNotNull($deletedDate);
     $this->assertTrue($this->task->validate());
     $this->task->save();
     //fetch updated entry for testing
     $stmt = $this->pdo->prepare('SELECT * FROM task WHERE id = :id');
     $stmt->execute(array(':id' => $id));
     $updated = $stmt->fetch();
     $this->assertNotNull($updated);
     $this->assertEquals($updateString, $updated['description']);
     $this->assertEquals($date->format('Y-m-d H:i:s'), $updated['dueDate']);
     $this->assertEquals(0, $updated['status']);
     $this->assertEquals(1, $updated['deleted']);
     $this->assertEquals($deletedDate->format('Y-m-d H:i:s'), $updated['deletedDate']);
     //remove data
     $stmt = $this->pdo->prepare('DELETE FROM task WHERE id = :id');
     $stmt->execute(array(':id' => $id));
 }
 /**
  * @param string $html
  * @return \Lunchbot\Menu\LunchMenuItem[]
  */
 public function parseHtml(string $html) : array
 {
     $crawler = new Crawler();
     $crawler->addContent($html);
     $rows = $crawler->filter('div.entry-content table tr')->each(function (Crawler $node) {
         return $node;
     });
     $todayDayOfWeek = (int) $this->today->format('N');
     $currentDayBlock = false;
     /** @var Crawler $item */
     $result = [];
     foreach ($rows as $item) {
         $headlineTag = $item->children();
         $headline = $headlineTag->text();
         $dayOfWeek = \Nette\Utils\Strings::match($headline, '~^(\\w+)\\s~u')[1] ?? null;
         if (isset(self::$DAYS[$dayOfWeek])) {
             if ($currentDayBlock) {
                 break;
                 // found tomorrow menu block
             } elseif (self::$DAYS[$dayOfWeek] === $todayDayOfWeek) {
                 $currentDayBlock = true;
             }
         } elseif ($currentDayBlock) {
             if (\Nette\Utils\Strings::trim($headline) === 'Dezert') {
                 break;
             }
             $result[] = new LunchMenuItem($headlineTag->siblings()->text());
         }
     }
     return $result;
 }