How do I print strings instead of the date?

Hi all

I need a little help creating a date function.
I’m wondering how I can print a string instead of the date, based on certain conditions.

If date = today print today
If date = tomorrow print tomorrow
and so on…

The below works and prints ‘today’ (small example of what I’m trying to do).

function print_datestrings() {
  
  $datetoday = date('Y-m-d') == date('Y-m-d', strtotime('now'));
  
  if ($datetoday == date('now')) {
    print "today";
  } else if ($datetoday == date("+1 day")) {
    print "tommorrow";
  } else if ($datetoday == date("-1 day")) {
    print "yesterday";
  } else {
    print $datetoday;
  }
}
print_datestrings();

Though what I really need is a function I can simply attached to a condition/variable which will check the dates and print the strings accordingly.
Today and tomorrow strings can be printing numerous times from a loop. I could have 6 events running today for example which would need to print today, maybe 4 events for tomorrow which would all print tomorrow.

Examples - which would be inside a foreach loop:

$data = print_datestrings($node->title);

or

$date = print_datestrings(date('l, j F', $timestamp));

Any suggestions, what I need to do?
Ideally, a function I can use again and again for different projects.

Thanks,
Barry


function dateString(DateTime $dt) {
    $now = new DateTime();
    $diff = $now->diff($dt);
    $days = $diff->days;
	if ($now > $dt) {
		$days *= -1;
	}
	
	switch (true) {
	    case $days === 0:
		    return 'today';
		case $days === 1:
			return 'tomorrow';
		case $days > 1:
			return 'in '.$days.' days';
		case $days === -1:
			return 'yesterday';
		default:
			return abs($days).' days ago';
	}
}

echo dateString(new DateTime());
echo '<br />';
echo dateString(new DateTime('+1 day'));
echo '<br />';
echo dateString(new DateTime('+3 day'));
echo '<br />';
echo dateString(new DateTime('-1 day'));
echo '<br />';
echo dateString(new DateTime('-3 day'));
echo '<br />';
echo dateString(new DateTime('-10 day'));
echo '<br />';

/** OUTPUT:
today
tomorrow
in 3 days
yesterday
3 days ago
10 days ago
*/

Something like that? :slight_smile:

(uses the DateTime class, and thus requires PHP >= 5.2, which every respectable host should have by now.)

Something like that?

Exactly like that ScallioXTX! :smiley:
This is just what I need, which makes it easy for me to add different cases inside the switch, perfect!

Just one issue, whenever I add this function I keep getting the error:

Recoverable fatal error: Argument 1 passed to dateString() must be an instance of DateTime, string given, called in /home/…

Are you familiar with this, something I’ve missed?

Example:

$date = dateString(date('l, j F', $timestamp));

Cheers,
Barry

FIXED.

I needed to add new DateTime as well :cool:

$date = dateString(new DateTime(date('l, j F', $timestamp)));

Thanks a lot.

UPDATE - Couple of problems.
It now prints how many days for every date, is there a way or how do I only print the string for, say, today, tomorrow and yesterday, and maybe all the past events?
Its also adding today for events tomorrow?

Barry

I’ve just read on PHP.net

When calculating with the date() function it was more accurate (didn’t use seconds/hours for comparison).

Is this what’s causing some events to show up for today instead of tomorrow?
Example if an event is tomorrow but only 6 hours away, is that being classed as today. Just a thought.

If so, how do we fix it?

That’s probably the issue, yes. Just make sure both dates are for midnight, so time doesn’t play a role, just the date. Like so


function dateString(DateTime $dt) {
    $dt->modify('midnight');
    $now = new DateTime('midnight');
    $diff = $now->diff($dt);
    $days = $diff->days;
    if ($now > $dt) {
        $days *= -1;
    }
    
    switch (true) {
        case $days === 0:
            return 'today';
        case $days === 1:
            return 'tomorrow';
        case $days > 1:
            return 'in '.$days.' days';
        case $days === -1:
            return 'yesterday';
        default:
            return abs($days).' days ago';
    }
}

It now prints how many days for every date, is there a way or how do I only print the string for, say, today, tomorrow and yesterday, and maybe all the past events?

I’m not sure I follow. Should it output nothing for future events?

Is the switch statement missing breaks?

Just make sure both dates are for midnight, so time doesn’t play a role, just the date.

$dt->modify('midnight');
$now = new DateTime('midnight');

Works great first time, thank you :cool:

Should it output nothing for future events?

In theory yes, just for today, tomorrow and yesterday, and maybe if possible to add my own dates, new cases maybe?
Everything else would print/default to the full date, thats what it already did before we adding the function.

While you was away, I was trying to fix it and managed to add both.
So now I have the full date with the day count to the right in <span>, looks quite good. Not sure if its the best way though seems to work. Saturday, 24 May Today.

$date = date('l, j F', $timestamp) .' <span> '. dateString(new DateTime(date('l, j F', $timestamp))) . '</span>';

Ideally, I’ll need to show the date for future events, If its something straight forward it would be nice to have the option so I can customise and use what works best.

Cheers,
Barry

Is the switch statement missing breaks?

Thanks John, I think the breaks have been left off so we carry on looping through to check all dates. Unless I’m mistaken?

They’re not there, but that doesn’t mean they’re missing :wink:
Since all cases do a return, it’s not necessary because cases can’t fall through.
You could add break to all of the cases, but the behavior would stay exactly the same, so I opted to leave them out.

So for example:


function x($a) {
    switch ($a) {
        case 1:
            return "hello";
        case 2:
            return "world"
        default:
            return $a;
    } 
}
echo x(1); // hello
echo x(2); // world

if $a is 1, the function will return “hello” and stop there. No other code of the function will be executed. If there were a break after return "hello" it wouldn’t be reached, so there isn’t point in putting it there.

Thanks ScallioXTX
Did you manage to have a quick look at my last post.

Something in the way of:

Yesterday
Today
Tomorrow
Saturday, 26 May
Saturday, 27 May
and so on…

Mainly the future events I need the date for, excluding tomorrow.

Also wondering, do you prefer using a switch statement over if else?
Is there much benefit using one over the other?

Cheers, Barry

I’m confused. You’re already showing those dates, aren’t you?

As for switch vs if I usually prefer if, unless it would get too many branches like here, then I think switch is more clear.

I’m confused. You’re already showing those dates, aren’t you?

Initially yes. When we added the function the dates were removed and replaced with today, tomorrow and how many days.

Example:

$date = dateString(new DateTime(date('l, j F', $timestamp)));

Prints:
2 days ago
yesterday
today
tomorrow
3 days

I then added, which you’re probably referring to:

$date = date('l, j F', $timestamp) .' <span> '. dateString(new DateTime(date('l, j F', $timestamp))) . '</span>';

Prints:
Thursday, 22 May 2 days ago
Saturday, 24 May yesterday
Sunday, 25 May today
Monday, 26 May tomorrow
Wednesday, 28 May 3 days

I was printing the date and number of days together just as a test, to see if I could do it.
There will be times where I’ll use both together, though most times I don’t need both and just need:

Yesterday
Today
Tomorrow
Saturday, 26 May
Saturday, 27 May
and so on…

Your initial function works great, we just need to change the future events to show the date, instead of number of days if that makes sense.
Sorry for the confusion.

Thanks, Barry

Ok I will try later today on the desktop.

I thought the missing breaks may be the reason why “today” was not showing.

In that case it’s probably easiest to return nothing from the function if the date is in the future, since you’re already printing the date on all events anyway. Which is easy enough:


function dateString(DateTime $dt) {
    $dt->modify('midnight');
    $now = new DateTime('midnight');
    $diff = $now->diff($dt);
    $days = $diff->days;
    if ($now > $dt) {
        $days *= -1;
    }
    
    switch (true) {
        case $days === 0:
            return 'today';
        case $days === 1:
            return 'tomorrow';
        case $days === -1:
            return 'yesterday';
        case $days < -1:
            return abs($days).' days ago';
        default:
            return "";
    }
}

Thanks.
Starting to make sense.

Now nothing is returned, today, tomorrow show ok, the date just stays blank?

What is happening when I use both:

$date = date('l, j F', $timestamp) . '<span>' . dateString(new DateTime(date('l, j F', $timestamp))) . '</span>';

Sunday 25 may today
Tuesday 27 may

So, the function is working just in the wrong context.

$date = dateString(new DateTime(date('l, j F', $timestamp)));

today
tomorrow
blank
blank

Barry

Could you please some more examples of what you want? I’m completely at a loss. I though this was what you wanted? :confused:

Ok.

Before we started this thread, everything was printing just the dates without the function, using the below snippet.

$date = date('l, j F', $timestamp)

Monday 12 May
Tuesday 13 May
Wednesday 14 May
Thursday 15 May

Then, when we wrapped the function around it, instead of the dates showing, we printed the strings, this is exactly what I needed, to a certain degree anyway.

$date = dateString(new DateTime(date('l, j F', $timestamp)))

2 days ago
Yesterday
Today
Tomorrow
1 day away

Though, I need the future events(after tomorrow) to print the date, as shown below.

2 days ago
Yesterday
Today
Tomorrow
Monday 26 may
Tuesday 27 May

Friday 20 June

Example, if I have an event in 2 months time it will show something like 62 days, I need to show the date.

And with the latest update to the function, the future dates have no value and stay blank.

Yesterday
Today
Tomorrow
no value
no value
no value

How this makes sense :cool:

Barry

Like this!?


function dateString(DateTime $dt) {
    $dt->modify('midnight');
    $now = new DateTime('midnight');
    $diff = $now->diff($dt);
    $days = $diff->days;
    if ($now > $dt) {
        $days *= -1;
    }

    switch (true) {
        case $days === 0:
            return 'today';
        case $days === 1:
            return 'tomorrow';
        case $days === -1:
            return 'yesterday';
        case $days < -1:
            return $abs($days).' days ago';
        default:
            return $dt->formay('l, j F');
    }
}

Perfect! :smiley:
Thanks a lot ScallioXTX

default: 
            return $dt->format('l, j F');

I was trying all kinds of crazy stuff, the closest I got was the below which just printed todays date:

default:
            return date('l, j F');

If you have a minute, one last question :cool:

We now have two instances of this function, nearly identical, from your first post and last post, couple of small changes to the switch cases, which display a mixture of dates and strings. I’ll most likely won’t to use this function in both instances further down the line.

My question - Will I need to create two separate functions if I won’t to use them in the two different instances?
I mean, we are making one small change to the switch case, do we need to repeat all that code, or is there a way combining the two into the same function.

Can we give each switch a name maybe and pass that name with the function when we call it?

Another important question - What happens when the events get past 365 days, will the function start printing the years + days, or print something like 487 days?
Is it possible to add year + days once the events get past a certain age?

Barry

You could add a parameter to the function and depending on the value of that parameter change the output.

Right now you will just get the number of days. You can change it to get the number of years etc. Look at the manual of DateTimeInterval, of which $diff is an instance :slight_smile: