I've seen a number of questions and answers on StackOverflow covering the scenario where timestamps have been based on the Unix Epoch but have been struggling to combine the solutions and modify them into a working solution for the data and custom base year I've been supplied.
<?php
date_default_timezone_set( 'Europe/London' );
function TransformDate( $iTimeStamp ) {
/* Insert transform code here */
$dt = new DateTime( '#' . $iTimeStamp );
return $dt->format( 'Y-m-d H:i:s' );
}
/* These timestamps should be between Sep-2014 and Jan-2015 */
$aTest = array( '-1554460973', '-1554427073', '-1554142396', '-1554139421' );
foreach( $aTest as $i ) echo( $i . ' - ' . TransformDate( $i ) . "\r\n" );
The only information I have to help process these timestamps is that they are based on the year 2013, with 10 ticks per second, and the data was originally from a Microsoft Jet database (so I would imagine similar data storage types to Microsoft Access etc).
I have tried so many combinations of adding or substracting the strtotime result value of 2013-01-01 and 1899-12-30, and multiplying and dividing by 10 that I've simplylost track now. For example:
$iTimeStamp -= strtotime( '2013-01-01' );
$iTimeStamp += strtotime( '1899-12-30' );
$iTimeStamp = round( $iTimeStamp / 10 );
So far though the closest I've got though is dates in 2012, though the December 31st 14:38pm part of the the date could be right:
$iTimeSinceBase = ( $iTimeStamp - strtotime( '2013-01-01' )) / 86400;
$iTimeStamp = strtotime( '2013-01-01' ) + $iTimeSinceBase;
The output for which is:
-1554460973 = 2012-12-31 14:38:22
-1554427073 = 2012-12-31 14:38:22
-1554142396 = 2012-12-31 14:38:26
-1554139421 = 2012-12-31 14:38:26
At this point any assistance is welcome! Thank you.
Related
There is a WordPress and ACF field with a date in the format 2022-04-30. From this date need to calculate 2 other dates, -2 days and +25 days. The problem is that it is necessary to take into account only working days, i.e. check weekends and holidays.
For example, we set the date May 3, 2022, which is Tuesday. From this date, I need to subtract 2 days, i.e. May 1, 2022, but this is Sunday, so we have to return to the first working day before May 1, i.e. Friday April 29, 2022. It's the same with holidays.
At the moment I have this code:
$setDate = get_field('set_date'); // ACF field, set May 3, 2022 (2022-05-03)
$offDate = wp_date('j F Y', strtotime('-2 days', strtotime($setDate)));
echo $offDate; // returns Sunday, May 1, 2022
I found holidays and weekends in json https://github.com/d10xa/holidays-calendar/blob/master/json/consultant2022.json
So I need to compare the given date with the dates from json and if there is a match, then minus one day and check the received date again. If there is a match, again minus one day and so on until no matches are found. Am I thinking correctly and can you tell me how to implement it? I am a very bad programmer, but there is a task)
At the moment I was only able to compare the dates and return the result found/not found. But I can't figure out how to take days off on the basis of this and send it for verification again(
$setDate = '2022-05-01';
$file = file_get_contents('https://raw.githubusercontent.com/d10xa/holidays-calendar/master/json/consultant2022.json', true);
$data = json_decode($file);
$found = array_search($setDate, $data->holidays);
if ($found === False) {
echo 'Not Found';
} else {
echo 'found';
}
The following has been tested on a few dates and I think it works as it should.
/*
JSON file is saved locally to a sub-directory
for the current working script directory.
This is to avoid unneccessary hits to the
remote site.
*/
$format='Y-m-d';
$url='https://raw.githubusercontent.com/d10xa/holidays-calendar/master/json/consultant2022.json';
$setDate = '2022-05-01';
$filepath=sprintf('%s/json/%s', __DIR__, basename( $url ) );
if( !file_exists( $filepath ) ){
file_put_contents( $filepath, file_get_contents( $url ) );
}
# read the file and generate JSON
$json=json_decode( file_get_contents( $filepath ) );
$hols=$json->holidays;
# create the initial DateTime object and find which weekday we are dealing with
# where 1 (for Monday) through 7 (for Sunday)
$obj=new DateTime( $setDate );
$date=$obj->format( $format );
$day=$obj->format('N');
# Is the given date a holiday/weekend?
if( array_search( $date, $hols ) ){
if( $day > 5 ){
# Date is either Sat or Sun... go back to previous working day
$subtract = 2 - ( 7 - $day );
$int=new DateInterval( sprintf('P%sD', $subtract ) );
$obj=new DateTime( $setDate );
$previous=$obj->sub( $int );
}else{
$previous=$obj->sub( new DateInterval('P2D') );
}
# create the future date ( add 25 days )
$int=new DateInterval('P25D');
$obj=new DateTime( $setDate );
$future=$obj->add( $int );
if( array_search( $future->format( $format ), $hols ) ){
# Future date is a holiday... go back to previous working day
$day=$future->format('N');
$subtract = 2 - ( 7 - $day );
$int=new DateInterval( sprintf('P%sD',$subtract ) );
$future=$future->sub( $int );
}
}else{
# Given date is NOT a holiday...
# take a copy of the original DateTime object for generating future date.
$ref=new DateTime( $setDate );
$int=new DateInterval( 'P2D' );
$previous=$obj->sub( $int );
$day=$previous->format('N');
# Is this a holiday?
if( $day > 5 ){
# yes - go back to previous working day
$subtract = 2 - ( 7 - $day );
$int=new DateInterval( sprintf('P%sD',$subtract ) );
$previous=$previous->sub( $int );
}
$int=new DateInterval('P25D');
$future=$ref->add( $int );
$day=$future->format('N');
# Is this a holiday?
if( $day > 5 ){
$subtract = 2 - ( 7 - $day );
$int=new DateInterval( sprintf('P%sD',$subtract ) );
$future=$future->sub( $int );
}
}
printf(
'<pre>
Given date: %s
Previous (-2): %s
Future (+25): %s
</pre>',
$date,
$previous->format( $format ),
$future->format( $format )
);
Which yields:
Given date: 2022-05-01
Previous (-2): 2022-04-29
Future (+25): 2022-05-26
A site contains monthly data in a JSON format. This can be queried like so:
http://www.example.com?startdate=1-1-1985&enddate=31-1-1985
I want to be able to run a script that will obtain the specific data I am looking for, starting from today's month, then work backward until null data is returned. Each month's value needs to add up. So far, this is what I've got:
//Build base URL:
$userid=$_GET['userid'];
$startdate=/*Beginning of today's month*/;
$enddate=/*End of today's month*/;
$url='http://www.example.com?userid='.$userid.'&startdate='.$startdate.'&enddate='.$enddate;
//Set JSON variables:
$get=file_get_contents($url);
$json=json_decode($get);
//Set loop variables:
$value=0;
$month=0;
/*For each month from today backwards{
$number=$json->integer;
if($number!=null){
$value=$value+$number;
$month=$month+1;
}else{
break;
}
}
echo $value;
echo $month;
*/
The part I'm having problems with is the beginning of the fourth part. How do I run a loop that starts with the range of today's month, obtain $number, then repeat with the previous month, until it reaches a month that returns null?
You could use the DateTime object and it's associated methods ( specifically sub in this case ) to count backwards by subtracting 1month at a time. An array stores the months/dates and the url is constructed using the variable counter $i
Initially this has a maximum backwards range of 20years ( which I guessed would be more than enough ) but it's easy to change.
$df='Y-m-d';
$userid=$_GET['userid'];
$timezone=new DateTimeZone('Europe/London');
$interval=new DateInterval('P1M');
$ts=date( $df, strtotime( date('Y-m-1') ) );
$tf=date( $df, strtotime( date('Y-m-1'). ' - 20 years') );
$start=new DateTime( $ts, $timezone );
$end=new DateTime( $tf, $timezone );
$dates=array();
$i=0;
while( $start->sub( $interval ) > $end ){
$dates[]=$start->format( $df );
if( $i > 1 ){
$startdate=$dates[ $i - 1 ];
$enddate=$dates[ $i ];
$url='http://www.example.com?userid='.$userid.'&startdate='.$startdate.'&enddate='.$enddate;
echo $url,'<br />';
/* uncomment when happy with mechanism */
/*
$data=file_get_contents( $url );
if( $data ) ) {
$json=json_decode( $data );
#process.....
break;
}
*/
}
$i++;
}
A snippet of the output
http://www.example.com?userid=bobodaclown&startdate=2017-10-01&enddate=2017-09-01
http://www.example.com?userid=bobodaclown&startdate=2017-09-01&enddate=2017-08-01
http://www.example.com?userid=bobodaclown&startdate=2017-08-01&enddate=2017-07-01
http://www.example.com?userid=bobodaclown&startdate=2017-07-01&enddate=2017-06-01
http://www.example.com?userid=bobodaclown&startdate=2017-06-01&enddate=2017-05-01
http://www.example.com?userid=bobodaclown&startdate=2017-05-01&enddate=2017-04-01
http://www.example.com?userid=bobodaclown&startdate=2017-04-01&enddate=2017-03-01
By using strtotime() and mktime() functions you can while loop until you get Null results. The below code will print 5 urls for 5 months. Change while condition accordingly.
// define $i
$i=0;
$userid = '343';//$_GET['userid']; //dont forget to replace with userid
do{
$timestring = strtotime("now -$i month");
//get Month
$month = date('m',$timestring);
//get Year
$year = date('Y',$timestring);
// First date Month and Year
$startdate = date('d-m-Y', mktime(0, 0, 0, $month, 1, $year));
// Last date Month and Year
$enddate = date('d-m-Y', mktime(0, 0, 0, $month+1, 0,$year));
$url='http://www.example.com?userid='.$userid.'&startdate='.$startdate.'&enddate='.$enddate;
// commenting your code
//Set JSON variables:
//$get=file_get_contents($url);
//$json=json_decode($get);
// $number=$json->integer;
echo $url;
echo "\n";
$i++;
}while ($i!=5); // change while condition according to your requirement. while ($number!=null)
Out Put:
http://www.example.com?userid=343&startdate=01-12-2017&enddate=31-12-2017
http://www.example.com?userid=343&startdate=01-11-2017&enddate=30-11-2017
http://www.example.com?userid=343&startdate=01-10-2017&enddate=31-10-2017
http://www.example.com?userid=343&startdate=01-09-2017&enddate=30-09-2017
http://www.example.com?userid=343&startdate=01-08-2017&enddate=31-08-2017
What would be the best way of converting UK date and time in the format:
30/01/2013 13:30:06
which is d/m/Y H:i:s in PHP noation to relative time (i.e. just now, few minutes ago, 30 minutes ago, 3 hours ago, 1 day ago.. and so on). I've seen several tutorials on the subject but they all revolve around creating functions without any clear explanations. I would appreciate some assistance on the matter.
Hope This helps
function timeSince($ptime){
$etime = time() - strtotime($ptime);
if( $etime < 1 ){
return 'less than 1 second ago';
}
$a = array( 12 * 30 * 24 * 60 * 60 => 'year',
30 * 24 * 60 * 60 => 'month',
24 * 60 * 60 => 'day',
60 * 60 => 'hour',
60 => 'minute',
1 => 'second'
);
foreach( $a as $secs => $str ){
$d = $etime / $secs;
if( $d >= 1 ){
$r = round( $d );
return ' <font style="color:#0099ff"> ' . $r . ' ' . $str . ( $r > 1 ? 's' : '' ) . ' ago</font>';
}
}
}
Writing a custom function might help. Cut the string and convert to numbers. Use mktime() to create a timestamp, compare it to time() current timestamp and switch (case) through various relative time possibilities.
Use mktime(); and date();
For example if you have a specific time in the format d/m/Y H:i:s, and you want it as d-m-Y H:s:i, you would explode the time into chunks using explode(); and then use date(new_format, mktime(current_format_chunks))
dd/mm/yyyy needs to be changed to dd.mm.yyyy according to the formatting rules otherwise it will be treated as mm/dd/yyyy
$dateString = '30/01/2013 13:30:06';
$dateObject = new DateTime(str_replace('/', '.', $dateString));
with the optional addition of a DateTimezone as a second argument to the DateTime constructor.
Then you can do a diff with the current date, and use dateintervals to get the relative time
The most straight-forward and friendly way of parsing dates is the DateTime extension. It has a static method called createFromFormat:
$date = '30/01/2013 13:30:06';
$format = 'j/m/Y G:i:s';
$time = DateTime::createFromFormat($format, $date);
echo $time->format('l dS F \'y at H.i.s');
The method takes a custom format and a date string. Because you can define the format yourself it is much easier than parsing it "manually".
In order to adjust the date you can use the add(), sub() and modify() methods:
$time->add(new DateInterval('P3DT5H')); // 3 days and 5 hours
echo $time->format('l dS F \'y at H.i.s');
$time->sub(new DateInterval('P9DT1H')); // 9 days and 1 hours
echo $time->format('l dS F \'y at H.i.s');
$time->modify('-1 year -35 days');
echo $time->format('l dS F \'y at H.i.s');
As you can see the modify() method is slightly easier to use. The two other methods use the DateInterval class and an awkward format. It is not difficult (just read the documentation and do as it says), but using actual words (i.e. "-3 days -7 hours") is easier to understand.
I have two variables stored in my database containing the following data:
$date_published = 2012-05-04 00:00:00; //Straight from DB datetime field
$advert_duration = 15;
I want to show an advert for 15 days from the date it was published. To do so I need to work out the time difference.
I have read various places online about calculating time difference and have come up with the below code
In my attempt to work out the equation I can't seem to calculate the differences between $now - the date today, the $date_published and the $advert_duration. I can't get the correct result:
function days_left($date_published, $advert_duration){
$date = new DateTime($date_published);
$now = new DateTime();
$days_elapsed = $date->diff($now)->format("%d");
$days_left = $advert_duration - $days_elapsed;
return $days_left;
}
function getDaysLeft( $date, $duration )
{
// create $date and modify it by $duration
$date = new DateTime( $date );
$date->modify( sprintf( '+%d days', $duration ) );
// calculate the difference
$now = new DateTime();
$daysElapsed = (int) $now->diff( $date )->format( '%a' );
// set to negative value, if modified $date is before $now
if( $date < $now )
{
$daysElapsed = $daysElapsed * -1;
}
return $daysElapsed;
}
var_dump(
getDaysLeft( '2012-05-04 00:00:00', 15 ),
getDaysLeft( '2012-07-04 00:00:00', 15 )
);
If you're fetching your ad from the database, you can simply use a date function to calculate this :
WHERE DATE_SUB(CURDATE(),INTERVAL 15 DAY) >= date
Or you can do this in PHP (you'll get an UNIX timestamp) :
$date = strtotime('+15 days', strtotime($date_published));
Is there a painless way to convert unix timestamps, MySQL timestamps, MySQL datetimes (or any other standard date and time format) into strings in the following form:
Today, 6:00pm
Tomorrow, 12:30pm
Wednesday, 4:00pm
Next friday, 11:00am
I'm not sure what to call these - I guess conversational-style, current time sensitive date formats?
As best I can tell, there is no native function for this. I have created (the start of) a function to do what you are wanting.
function timeToString( $inTimestamp ) {
$now = time();
if( abs( $inTimestamp-$now )<86400 ) {
$t = date('g:ia',$inTimestamp);
if( date('zY',$now)==date('zY',$inTimestamp) )
return 'Today, '.$t;
if( $inTimestamp>$now )
return 'Tomorrow, '.$t;
return 'Yesterday, '.$t;
}
if( ( $inTimestamp-$now )>0 ) {
if( $inTimestamp-$now < 604800 ) # Within the next 7 days
return date( 'l, g:ia' , $inTimestamp );
if( $inTimestamp-$now < 1209600 ) # Within the next 14, but after the next 7 days
return 'Next '.date( 'l, g:ia' , $inTimestamp );
} else {
if( $now-$inTimestamp < 604800 ) # Within the last 7 days
return 'Last '.date( 'l, g:ia' , $inTimestamp );
}
# Some other day
return date( 'l jS F, g:ia' , $inTimestamp );
}
Hope that helps.
You should read the docs for strftime and strtotime
An example of converting UNIX timestamp to your format:
$time = time(); // UNIX timestamp for current time
echo strftime("%A, %l:%M %P"); // "Thursday, 12:41 pm"
To get a MySQL datetime value, assuming it comes out of the database as "2010-07-15 12:42:34", try this:
$time = "2010-07-15 12:42:34";
echo strftime("%A, %l:%M %P"); // "Thursday, 12:42 pm"
Now, in order to print the word "today" instead of the day name you will have to do some additional logic to check if the date is today:
$time = "2010-07-15 12:42:34";
$today = strftime("%Y-%m-%d");
// compare if $time strftime's to the same date as $today
if(strftime("%Y-%m-%d", $time) == $today) {
echo strftime("Today, %l:%M %P", $time);
} else {
echo strftime("%A, %l:%M %P", $time);
}
The strtotime shoule be useful for that.
Example:
echo date('d, h:i:sa', strtotime($date_orig));
PHP date funcs are kind of messy because they have so many different ways, and even new classes were built over the old ones. For that type of formatting, what I call human-friendly formatting, you're going to have to write your own function that does it.
For conversion, you can use strtotime() as mentioned, but if you're dealing with epoch times and need utc GMT times, heres some functions for that. strtotime() would convert the epoch time to the local server time... this was something I don't want on my projects.
/**
* Converts a GMT date in UTC format (ie. 2010-05-05 12:00:00)
* Into the GMT epoch equivilent
* The reason why this doesnt work: strtotime("2010-05-05 12:00:00")
* Is because strtotime() takes the servers timezone into account
*/
function utc2epoch($str_date)
{
$time = strtotime($str_date);
//now subtract timezone from it
return strtotime(date("Z")." sec", $time);
}
function epoch2utc($epochtime, $timezone="GMT")
{
$d=gmt2timezone($epochtime, $timezone);
return $d->format('Y-m-d H:i:s');
}
If you are pulling this type of data out of your database
$time = "2010-07-15 12:42:34";
then do this
$this->db->select('DATE_FORMAT(date, "%b %D %Y")AS date');
Look here for info to display your data any way you want in human form
http://www.w3schools.com/SQL/func_date_format.asp
The above code is in codeigniter format, but you can just convert it to a SELECT statement for MYSQL
$query = "SELECT `title`,`post`, DATE_FORMAT(date, "%a, %d %b %Y %T") AS date FROM `posts` LIMIT 0, 8 ";
You will want to change the %a letters to fit your needs.
you will get exact result::
output // 28 years 7 months 7 days
function getAge(dateVal) {
var
birthday = new Date(dateVal.value),
today = new Date(),
ageInMilliseconds = new Date(today - birthday),
years = ageInMilliseconds / (24 * 60 * 60 * 1000 * 365.25 ),
months = 12 * (years % 1),
days = Math.floor(30 * (months % 1));
return Math.floor(years) + ' years ' + Math.floor(months) + ' months ' + days + ' days';
}