Create empty date for specific format in PHP - php

I would like to get date string filled with zeros for specified date format. I want to use it in case when there is no date given by external API.
Example:
define('DATE_FORMAT', 'Y-m-d H:i:s');
[...]
$date = SomeExternalApi::get_date();
// if date is given it's simple
if(!empty($date)){
$date_obj = DateTime::createFromFormat(SomeExternalApi::SOME_DATE_FORMAT, $date_string);
return $date_obj->format(DATE_FORMAT);
}else{
// SO UGLY BELOW! :( How to use DATE_FORMAT in this case?
return '0000-00-00 00:00:00';
}
I don't want to hardcode "zero string" like in example, because when I change DATE_FORMAT I would like to get zeros formatted new way.
Probably there is no simple way to format "zero string" of date, but maybe someone from this great community has better idea? :)

The best answer for my question is: DON'T GO THIS WAY.
You will never need empty date with zeros - it's super uncommon. The only one place where you can find it is database date field - if there is no date, you will get zeros format. But this will be always the same format, so you can define it as constant and condition as string.
Zeros as I asked are BAD because if you send such zeros through some API to any client like mobile app it has no chance to parse it - it will crash the app without catching errors.
Instead of having zeros date presentation use:
[when saving] put empty string in database, you can set date field to empty string and this will become zeros, do it with UPDATE mytable SET date = "" WHERE id = 2; and mytable.date field is MySQL timestamp in this example,
[when getting] you will get zeros with SELECT date FROM mytable WHERE id = 2;, so define it in your code as constant string 0000-00-00 00:00:00 and equal with returning value from db,
[when response of API] if date is empty return false instead of zeros. Mobile app can check if it's false and try to parse it in any other case. It's the best way to keep empty date and is super simple to check in any format by any language. Lot of simpler than trying to parse some strange zeros format.
Generally if I find date by condition like in example I return false and every single client using this API is happy with it:
if(empty($date)){return false;}

Dates and times in PHP are represented with a UNIX timestamp. The range of possible dates this can represent is not capable of representing the timestamp '0000-00-00 00:00:00' on a 32-bit system (it's over 2000 years ago). Also, actually creating a DateTime representing this single timestamp is probably pretty pointless, the values it represents are unchanging.
However, you could do this by defining absolute values for every sensible format character and using strtr() to convert them to their specific values.
Short example using your example input format:
$placeholders = array(
'Y' => '0000',
'm' => '00',
'd' => '00',
'H' => '00',
'i' => '00',
's' => '00'
);
return strtr(DATE_FORMAT, $placeholders);
However, this could start to get messy when you are dealing with the format elements that represent textual elements such as D. Personally I'd probably pick a default format and use that, as your code in the question shows.

Related

php 7.4 how to expect date format "ddmmYYYY"

I need to force the users to enter a date like this "ddmmYYYY" e.g : 14012022
The problem I'm facing is that I can't force this format just using this :
DateTime::createFromFormat('dmY', '14012022');
For example, DateTime::createFromFormat('dmY', '212022') for "02012022", it will not return false, although the date will still be wrong at the end.
Is there a way to force the user to pass the exact format that I expect, which is "ddmmYYYY" ?
I need 2 digits for the day, 2 digits for the month, and 4 digits for the year imperatively.
Thanks
How about an addition check by converting the date back to string?
$inputDate = '212022';
$date = DateTime::createFromFormat('dmY', $inputDate);
$valid = $date && $date->format('dmY') == $inputDate;
Since the manual says,
Letters that are used for parsing numbers allow a wide range of values, outside of what the logical range would be.
So string like '32132022' is valid input for createFromFormat, the above method will help you to avoid such date string.

how to add one month in a raw date coming from oracle using PHP only?

Let's say I have this date, e.g.:
12-DEC-14 11.55.51.000000000 AM
and then I assigned it to variable, let's say:
$date = '12-DEC-14 11.55.51.000000000 AM';
Now the question is, how do I add 1 month or 2 months or so to that $date using only
php, without using any oracle sql date functions, just pure php,
because I will save the result to oracle db table in that same format.
The result should be like, e.g.:
$nextmonth = '12-JAN-15 11.55.51000000000 AM';
Then that's the time I can save that $nextmonth in the table column. So how ?
You can use DateTime classes in this case, load that date and define its format. Then after creating the datetime object, adjust it to your x number of months, then present it again with the original format.
$input = '12-DEC-14 11.55.51.000000000 AM';
$date = DateTime::createFromFormat('d-M-y h.i.s A', $input);
$next_month = clone $date;
$next_month->modify('+1 month');
echo strtoupper($next_month->format('d-M-y h.i.s A'));
This is probably only a very long comment rather than a real answer, but some of your comments let me think we have an instance of XY problem here:
it's a TIMESTAMP(6) , but the format is exactly like this inside that column 12-DEC-14 11.55.51.000000000 AM
how bout the succeeding 9 zeroes ?, won't that cause any errors in oracle if I just append it like e.g echo strtoupper($next_month->format('d-M-y h.i.s.000000000 A'));
A TIMESTAMP(6) store a date-time information (a "point in time"). It hasn't any "format" par se. TIMESTAMP are great data type, as they allow you to easily perform calculation on data and time with a great precision at DB level such as "adding one month".
But, without explicit request from your part, a default format is used to convert timestamps from and to strings.
Maybe your real issue is that Oracle try to implicitly convert your string to timestamp using its standard format. Usually, it is a far better idea to explicitly convert data type yourself. From the documentation:
Oracle recommends that you specify explicit conversions, rather than rely on implicit or automatic conversions, for these reasons:
[...]
implicit conversion depends on the context in which it occurs and may not work the same way in every case. For example, implicit conversion from a datetime value to a VARCHAR2 value may return an unexpected year depending on the value of the NLS_DATE_FORMAT parameter.
Please note that above statement is true for TIMESTAMP too, as the "standard" format is user-definable using NLS_TIMESTAMP_FORMAT.
The PHP documentation has a similar warning:
DATE columns are returned as strings formatted to the current date format. The default format can be changed with Oracle environment variables such as NLS_LANG or by a previously executed ALTER SESSION SET NLS_DATE_FORMAT command.
As a personal suggestion, I would say that you should never rely on implicit date/timestamp conversion, as any change of the relevant configuration settings at DB-level or for the current session will break your code.
So, depending the way you insert your value, using an explicit format might be as simple as wrapping the bind variable in a proper TO_TIMESTAMP(....) call:
// query the original data
$q = oci_parse ($connection ,
"INSERT INTO ....
VALUES (TO_TIMESTAMP(:date_as_str, 'YYYY-MM-DD HH:MI:SS.FF'), other_columns...)");
$q = oci_parse ($connection ,
"INSERT INTO ....
VALUES (TO_TIMESTAMP(:date_as_str, 'YYYY-MM-DD HH:MI:SS.FF'), other_columns...)");
Coming back to your initial question: "how to add one month in a raw date" " I will save the result to oracle db table in that same format data type" , this should be as simple as adding 1 month when inserting the value:
$q = oci_parse ($connection ,
"INSERT INTO ....
VALUES (TO_TIMESTAMP(:date_as_str, 'YYYY-MM-DD HH:MI:SS.FF')
+ INTERVAL '1' MONTH, other_columns...)");

How to format date in PHP from a string of concatenated numbers?

I am new to PHP and I am trying to learn more of php date and time but I seem to get stuck with this.
I have this date format:
ddMMyyHHmmss
And an example is 120813125055 but I am trying to manipulate the string such that it will give me the format of:
yyyy-MM-dd HH:mm:ss (in the example above, 2013-08-12 12:50:55)
I tried to do something like:
date('Y-m-d H:i:s', strtotime('120813125055'));
But it always gives me a result of 1969-12-31 18:00:00.
I assume that I need to do some string manipulation in PHP for this but I was wondering if there is an easier and more efficient way to do it?
I think what you're looking for is in the second response answered here: how to re-format datetime string in php?
To summarize (and apply to your example), you could modify the code like this.
$datetime = "120813125055";
$d = DateTime::createFromFormat("dmyHis", $datetime);
echo $d->format("Y-m-d H:i:s");
Use date_create_from_format:
$ts = date_create_from_format('dmyHis', '120813125055');
$str = date('Y-m-d H:i:s', $ts);
strtotime() only works on EASILY recognizable formats. Your is a ugly mix of garbage, so no surprise that strtotime bails with a boolean FALSE for failure, which then gets typecast to an int 0 when you tried feed it back into date().
And of course, note that your time string is NOT y2k compliant. two digit years should never ever be used anymore, except for display purposes.
You're using your function call and the argument the wrong way around.
In your example, php will try to return you the date for which the time is 'strtotime('120813125055')', and this function returns false (interpreted as 0). So you get returned the date formatted in 'Y-m-d H:i:s' for the Unix epoch.
You will need to get the actual timestamp of your string, so use http://www.php.net/manual/en/datetime.createfromformat.php.
You are mistaken here..
I tried to do something like:
date('Y-m-d H:i:s', strtotime('120813125055'));
You shouldn't use only numbers ( doesnt matter its an integer or a string ), than it will always give you the same thing.
You can use any other valid date and time ( E.G. 6 Jun 2013, 5 may 12...) . Because what strtotime() do is detect a valid date and convert it into timestamp.

How to solve PHP date() NULL value 1969?

cI use jQuery calendar date picker on my form. When the date is not filled, it always shows "1969-12-31" value. I did not want to show this value, 0000-00-00 is fine for me.
My MySQL date column is receive_dt DATE NOT NULL,
This is a snippet code from the PHP file to handle the form.
...
$rcv_dt = $_POST['receive_dt'];
list($year,$month,$day)=explode('/',$rcv_dt);
$timestamp=mktime(0,0,0,$year,$month,$day);
$receive_dt=date('Y-m-d',$timestamp);
..., receive_dt) VALUES (....,'$receive_dt')...
I've tried to do the strtotime() but no luck.
$receive_dt=date('Y-m-d', strtotime($rcv_dt));
I've even changed the MySQL reveive_dt column to DATE NULL, but still no luck.
Firstly, the fact that you're getting the end of 1969 rather than the beginning of 1970 (the "Unix epoch" begins at midnight on 1st Jan 1970) suggests you have some timezone-handling bug causing you to "lose" an hour, so just a heads-up on that.
Now, the reason you're seeing this at all, is that PHP's date formatting functions treat whatever input you give them as a number; if you give them an empty string, or null, this will be converted to the number 0, and interpreted as the beginning of the Unix epoch - 1st Jan 1970. MySQL will probably do something similar if you try to pass it an empty string or 0 when populating the column.
What you need to do is specifically detect this case - easy enough if your application should never actually have 1st Jan 1970 as input - and specifically insert a NULL into the database rather than formatting the date.
$invalid_dates='1969-12-31'; // anything before
$rcv_dt = $_POST['receive_dt'];
if(strtotime($invalid_dates) >= strtotime($rcv_dt))
{
$rcv_dt='0000-00-00'; // or $rcv_dt=date('Y-m-d'); // today
}
http://php.net/manual/en/function.checkdate.php
Learn to use the DateTime object. Using strtotime, mktime, and other integer based time formats is an outdated and bad approach.
$dt = date_create($_POST['receive_dt']);
if ($dt !== null)
{
echo $dt->format('Y-m-d H:i:s'); // insert this value
}
if you send $receive_dt as an empty string ..., receive_dt) VALUES (....,'')... (after checking the post variable is empty) then mysql will treat is as a null, otherwise php is sending a date of 0 which for mysql is the start date of the unix epoch.

Format datetime from input string

I'm doing a date search filter where I have my date displayed as "j.n.Y G:i (26.6.2012 15:22)".
A user can enter the whole date or only a portion of it: "26.6","6.2012","6","15:22" are all valid inputs. Because I need to check this date in the database the format needs to be changed to the one of the database. For that I use:
$datum = '25.6.2012';
$date = DateTime::createFromFormat('j.n.Y',$datum);
echo $date->format('Y-m-d H:i');
Where I get an error if $datum is not in the format j.n.Y (if I only enter j.n or one of the above mentioned string portions i get an error).
A problem is also, for the entered string 'j.n.Y', i get the right output of the date, which also has the current time added to the date string (which was not in the initial date string). Example: I enter "22.6.2012", then I get the output "2012-06-22 15:33".
Can these two problems get fixed with existing php functions or should I make my own?
Help would be greatly appreciated.
You can list your acceptable data formats in an array, and loop around DateTime::createFromFormat() to see if any of the inputs produce an acceptable date:
$formats = array( 'j.n', 'j.n.Y');
$datum = '25.6.2012'; $date = false;
foreach( $formats as $format) {
$date = DateTime::createFromFormat( $format, $datum);
if( !($date === false)) break;
}
if( $date === false) {
echo "Invalid date!\n";
}
Finally, if you want to get rid of the current time in the newly created object and set the time to 00:00:00, just use the setTime() method on the date object:
// Sets the time to O hours, 0 minutes, 0 seconds
$date->setTime( 0, 0, 0);
For the first problem, you will need to write some code of your own because some of your acceptable inputs are not among the recognized input formats. Normalizing the input value will require you to fully parse it (a regular expression is a good way to start), and then you can call DateTime::createFromFormat without trouble.
For the second problem, putting an exclamation mark ! at the beginning of your format string would fix the time issue. From the documentation:
If format contains the character !, then portions of the generated
time not provided in format, as well as values to the left-hand side
of the !, will be set to corresponding values from the Unix epoch.
The Unix epoch is 1970-01-01 00:00:00 UTC.
However, since you are going to need to fully parse the input as mentioned above the matter is moot. Also note that the exclamation mark would cause missing values for year, month and day to use defaults that are probably undesirable.

Categories