Thursday, 18 November 2021

PHP Date and Time Recipes

Dealing with dates and times is one of those things that can frustrate programmers a lot. At the same time, they are fundamental to software development, used from everything from meta and how things are ordered to time-based triggers and lots in between.

Dates and times are prone to errors too. Handle them incorrectly, and they can confuse end-users and fellow programmers alike.

This is a quick guide to dealing with dates and times specifically in the PHP programming language. It’s meant to be a reference to the most common needs you’ll have, like formatting and adjusting dates. It’s simple, but it’s likely going to cover 80% of your needs.

Table of contents

This research is brought to you by support from Frontend Masters, CSS-Tricks’ official learning partner.

Need front-end development training?

Frontend Masters is the best place to get it. They have courses on all the most important front-end technologies. Interested in going full-stack? Here’s your best bet:


Get the current date and time

One thing to know is that the dates and times can be represented in three forms: a timestamp (i.e. epoch time), a DateTime object, and a string.

First up, a recipe to get the current date and time:

<?php

$now = new DateTime();
var_dump($now);

// object(DateTime)#1 (3) {
//   ["date"]=>
//   string(26) "2021-10-13 22:25:11.790490"
//   ["timezone_type"]=>
//   int(3)
//   ["timezone"]=>
//   string(12) "Asia/Jakarta"
// }

This provides a DateTime object that can be used to create a date and time string:

<?php

$now = new DateTime();
echo $now->format("Y-m-d"); // 2021-10-13
echo $now->format("Y-m-d h:i:s A"); // 2021-10-13 10:10:31 PM

Intuitively, you know that Y refers to the year, m refers to the month, d refers to the day of the month, and so on. The full list of the parameters can be found in the PHP manual, but I’ll drop some of the most common ones here for reference.

Day of the month
d Day of the month. two digits with leading zeros 01 – 31
j Day of the month without leading zeros 1 – 31
S Includes the English suffix. stndrdth (e.g. 1st2nd3rd4th)
Weekday
D Abbreviated textual representation of a day, in three letters Sun – Sat
l A full textual representation of a weekday. Sunday – Saturday
Month
F A full textual representation of a month, such as January or March January – December
M Abbreviated textual representation of a month, in three letters Jan – Dec
m Numeric representation of a month, with leading zeros 01 – 12
n Numeric representation of a month, without leading zeros 1 – 12
Year
Y A full numeric representation of a year, 4 digits E.g. 1999 or 2003
y A two digit representation of a year E.g. 99 or 03
Time
A Uppercase Ante Meridiem and Post Meridiem AM or PM
g 12-hour format of an hour without leading zeros 1 – 12
h 12-hour format of an hour with leading zeros 01 – 12
i Minutes with leading zeros 00 – 59
s Seconds with leading zeros 00 – 59

The DateTime object can be converted to a timestamp:

<?php

$now = new DateTime();
echo $now->getTimestamp(); // 1634139081

But we can also get the current time in timestamp without constructing a DateTime object:

<?php

echo time(); // 1634139081

Construct a DateTime object of a specific time

What if we want to construct a DateTime for a particular time, like July 14th, 2011? We can pass a formatted string date to the constructor:

<?php

$date = new DateTime("2011-07-14");
var_dump($date);

// object(DateTime)#1 (3) {
//   ["date"]=>
//   string(26) "2011-07-14 00:00:00.000000"
//   ["timezone_type"]=>
//   int(3)
//   ["timezone"]=>
//   string(12) "Asia/Jakarta"
// }

The constructor accepts other formats as well:

<?php

$date = new DateTime("14-07-2011");
var_dump($date);

// object(DateTime)#1 (3) {
//   ["date"]=>
//   string(26) "2011-07-14 00:00:00.000000"
//   ["timezone_type"]=>
//   int(3)
//   ["timezone"]=>
//   string(12) "Asia/Jakarta"
// }

But be careful with an ambiguous format, like this:

<?php

$date = new DateTime("07/14/2011");
var_dump($date);

// object(DateTime)#1 (3) {
//   ["date"]=>
//   string(26) "2011-07-14 00:00:00.000000"
//   ["timezone_type"]=>
//   int(3)
//   ["timezone"]=>
//   string(12) "Asia/Jakarta"
// }

You might think that everyone should be familiar with an American date format. But not everyone is and it might be interpreted differently. Not PostgreSQL.

CREATE TABLE IF NOT EXISTS public.datetime_demo
(
  created_at date
);

insert into datetime_demo (created_at) values ('07/12/2011');

select created_at from datetime_demo; /* 2011-12-07 */

You may have thought that would return July 12th, 2011, but it was December 7th, 2011, instead. A better way is to use an explicit format:

<?php

$date = DateTime::createFromFormat('m/d/y', "10/08/21");
var_dump($date);

//object(DateTime)#2 (3) {
//  ["date"]=>
//  string(26) "2021-10-08 16:00:47.000000"
//  ["timezone_type"]=>
//  int(3)
//  ["timezone"]=>
//  string(12) "Asia/Jakarta"
//}

What if we want to construct a DateTime object from a timestamp?

<?php

$date = new DateTime();
$date->setTimestamp(1634142890);
var_dump($date);

//object(DateTime)#1 (3) {
//  ["date"]=>
//  string(26) "2021-10-13 23:34:50.000000"
//  ["timezone_type"]=>
//  int(3)
//  ["timezone"]=>
//  string(12) "Asia/Jakarta"
// }

We don’t have to create a DateTime object if we want to convert a timestamp object to a formatted date string:

<?php

echo date("Y-m-d h:i A", time()); // 2021-10-14 04:10 PM

Timezones

We can create a DateTime object that includes timezone information, like if we’re dealing with Pacific Standard Time, Eastern Daylight Time, etc.

<?php

$timezone = new DateTimeZone("America/New_York");
$date = new DateTime("2021-10-13 05:00", $timezone);
var_dump($date);

// object(DateTime)#1 (3) {
//   ["date"]=>
//   string(26) "2021-10-13 05:00:00.000000"
//   ["timezone_type"]=>
//   int(3)
//   ["timezone"]=>
//   string(16) "America/New_York"
// }

// Eastern Daylight Time, for example: New York
$date = new DateTime("2021-10-13 05:00 EDT");
var_dump($date);

// object(DateTime)#2 (3) {
//   ["date"]=>
//   string(26) "2021-10-13 05:00:00.000000"
//   ["timezone_type"]=>
//   int(2)
//   ["timezone"]=>
//   string(3) "EDT"
// }

$date = new DateTime("2021-10-13 05:00 -04:00");
var_dump($date);

// object(DateTime)#1 (3) {
//   ["date"]=>
//   string(26) "2021-10-13 05:00:00.000000"
//   ["timezone_type"]=>
//   int(1)
//   ["timezone"]=>
//   string(6) "-04:00"
// }

There are three ways to create a DateTime object with timezone information. The timezone_type accepts different values for each one.

But say we want to convert a date and time that’s displayed in New York’s timezone to display Jakarta’s timezone instead?

<?php

$newYorkTimeZone = new DateTimeZone("America/New_York");
$date = new DateTime("2021-11-11 05:00", $newYorkTimeZone);
echo $date->format("Y-m-d h:i A"); // 2021-11-11 05:00 AM
$jakartaTimeZone = new DateTimeZone("Asia/Jakarta");
$date->setTimeZone($jakartaTimeZone);
echo $date->format("Y-m-d h:i A"); // 2021-11-11 05:00 PM

When it’s 05:00 AM in New York, it’s 05:00 PM in Jakarta on the same day. Jakarta is 12 hours ahead of New York on November 11th 2021. But one month earlier, Jakarta is only 11 hours ahead of New York as shown below:

<?php

$newYorkTimeZone = new DateTimeZone("America/New_York");
$date = new DateTime("2021-10-11 05:00", $newYorkTimeZone);
echo $date->format("Y-m-d h:i A"); // 2021-10-11 05:00 AM
$jakartaTimeZone = new DateTimeZone("Asia/Jakarta");
$date->setTimeZone($jakartaTimeZone);
echo $date->format("Y-m-d h:i A"); // 2021-10-11 04:00 PM

PHP handles Daylight Saving Time for you automatically.

Localization

This is a common way to display date and time in the United States:

<?php

$now = new DateTime();
echo $now->format("m/d/Y h:i A"); // 10/14/2021 03:00 PM

But someone in France might prefer something more common to their locale. C’est horrible, they’d complain. For one, nobody puts the month before month day, except the U.S. Second, France doesn’t use AM or PM — they use the 24-hour format (e.g. 14:00 instead of 2:00 PM) like the military. This is how you make a French local happy.

<?php

$now = new DateTime();
echo $now->format("d/m/Y H:i"); // 14/10/2021 15:00

But this requires an intimate knowledge about a specific country or area. Instead, we can localize the date. To localize a date in PHP, first check for support for a particular language.

In this example, we’re using the French. In Ubuntu, install the French language pack:

$ sudo apt-get install language-pack-fr

Use the strftime() function to localize a date:

<?php

setlocale(LC_TIME, "en_US.UTF-8"); // Check for U.S. English support
echo strftime("%x %X"); // 10/14/21 03:37:59 PM
setlocale(LC_TIME, "fr_FR.UTF-8"); // Check for French support
echo strftime("%x %X"); // 14/10/2021 15:37:31

All of the parameters for strftime are documented in the PHP manual.

Time travel

Let’s do time travel to the past and the future. First, let’s get acquainted with DateInterval:

<?php

$interval = new DateInterval("P4M1W2DT2H5M");

// P 4M 1W 2D T 2H 5M
//
// P = Period interval (years, months, weeks, days)
// 4M = 4 months
// 1W = 1 week
// 2D = 2 days
//
// T = Time interval (hours, minutes, seconds)
// 2H = 2 hours
// 5M = 5 minutes

The P and T are to separate period interval and time interval. Here’s how we can travel to the future:

<?php

$date = new DateTime("2021-10-14");
$interval = new DateInterval("P2D"); // 2 days
$futureDate = $date->add($interval);
echo $futureDate->format("Y-m-d"); // 2021-10-16

And here’s how we go back in time:

<?php

$date = new DateTime("2021-10-14 10:00");
$interval = new DateInterval("PT6H"); // 6 hours
$pastDate = $date->sub($interval);
echo $pastDate->format("Y-m-d H:i"); // 2021-10-14 04:00

If we want to time travel with the name of the weekday, we can combine the strtotime() function and the setTimestamp() method of a DateTime object:

<?php

$nextTuesday = strtotime("next tuesday");
$date = new DateTime("2021-10-14");
$date->setTimestamp($nextTuesday);
echo $date->format("Y-m-d"); // 2021-10-19

See the full list of strtotime() parameters in the PHP docs.

Recurring dates and times

It’s a common feature in calendar apps to set a reminder that repeats every so often, like every two days or every week. We can use DatePeriod to represent a period of time:

<?php

$start = new DateTime("2021-10-01");
$end = new DateTime("2021-11-01");
$interval = new DateInterval("P1W"); // 1 week
$range = new DatePeriod($start, $interval, $end);

// Starting from October 1st 2021 (inclusive), jump every 1 week
// until November 1st 2021 (exclusive)
foreach ($range as $date) {
  echo $date->format("Y-m-d") . "n";
}

// 2022-10-01
// 2022-10-08
// 2022-10-15
// 2022-10-22
// 2022-10-29

How many days ago?

You know how services like Twitter will show that someone posted X number of minutes/hours/days/etc. ago? We can do the same thing by calculating how much time has elapsed between the the current time and when that action occurred.

<?php

$date = new DateTime("2022-10-30");

$date2 = new DateTime("2022-10-25");
$date3 = new DateTime("2022-10-10");
$date4 = new DateTime("2022-03-30");
$date5 = new DateTime("2020-03-30");

function get_period_ago($endDate, $startDate) {
  $dateInterval = $endDate->diff($startDate);

  if ($dateInterval->invert==1) {
    if ($dateInterval->y > 0) {
      return $dateInterval->y . " years agon";
    } if ($dateInterval->m > 0) {
      return $dateInterval->m . " months agon";
    } if ($dateInterval->d > 7) {
      return (int)($dateInterval->d / 7) . " weeks agon";
    } if ($dateInterval->d > 0) {
      return $dateInterval->d . " days agon";
    }
  }
}

echo get_period_ago($date, $date2); // 5 days ago
echo get_period_ago($date, $date3); // 2 weeks ago
echo get_period_ago($date, $date4); // 7 months ago
echo get_period_ago($date, $date5); // 2 years ago

After getting the DateInterval object from the diff() method, make sure that the $startDate variable is in the past by checking the invert property. Then check the y, m, and d properties.

The full list of DateInterval object properties can be found here in the PHP docs.

Where do you go from here?

Now you have a little cheatsheet of common PHP recipes for when you find yourself working with dates and times. Need to get the current date and time? Maybe you need to format a date a certain way, or include the local timezone, or compare dates. All of that is right here!

There are still more methods and functions about date and time that we haven’t discussed, of course — things like calendar-related functions and whatnot. Be sure to keep the PHP Manual’s Date and Time section close by for even more use cases and examples.


The post PHP Date and Time Recipes appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/3DuGdjZ
via IFTTT

No comments:

Post a Comment

Passkeys: What the Heck and Why?

These things called  passkeys  sure are making the rounds these days. They were a main attraction at  W3C TPAC 2022 , gained support in  Saf...