PHP Integers with leading zeros - php

Particularly, 08 and 09 have caused me some major trouble. Is this a PHP bug?
Explanation:
I have a calendar 'widget' on a couple of our client's sites, where we have a HTML hard-coded calendar (I know a PHP function can generate n number of months, but the boss man said 'no').
Within each day, there is a PHP function to check for events on that day, passing the current day of the month like so:
<td valign="top">01<?php printShowLink(01, $events) ?></td>
$events is an array of all events on that month, and the function checks if an event is on that day:
function printShowLink($dayOfMonth, $eventsArray) {
$show = array();
$printedEvent = array();
$daysWithEvents = array();
foreach($eventsArray as $event) {
if($dayOfMonth == $event['day'] && !in_array($event['id'], $printedEvent)){
if(in_array($event['day'], $daysWithEvents)) {
echo '<hr class="calendarLine" />';
} else {
echo '<br />';
}
$daysWithEvents[] = $event['day']; // string parsed from timestamp
if($event['linked'] != 1) {
echo '<div class="center cal_event '.$event['class'].'" id="center"><span title="'.$event['title'].'" style="color:#666666;">'.$event['shorttitle'].'</span></div>';
$printedEvent[] = $event['id'];
} else {
echo '<div class="center cal_event '.$event['class'].'" id="center">'.$event['shorttitle'].'</div>';
$printedEvent[] = $event['id'];
}
}
}
}
On the 8th and 9th, no events will show up. Passing a string of the day instead of a zero-padded integer causes the same problem.
The solution is as what is should have been in the first place, a non-padded integer. However, my question is, have you seen this odd behavior with 08 and/or 09?
I googled this and couldn't find anything out there.

Quote it. 0123 without quotes is octal in PHP. It's in the docs
$ php -r 'echo 01234, "\n01234\n";'
668
01234
$
So you should change your code to
<td valign="top">01<?php printShowLink('01', $events) ?></td>

It's been a while since I've had to wade through so much PHP been doing mostly Javascript for 3 years. But 08 and 09 being a problem makes me think: they could be getting treated as octal (base 8), and the digits 8 and 9 do not exist in octal.

Related

show data only if currentmonth and currentyear are larger than

Let say currentmonth is 06 and currentyear 2017
i have dropdown of year and month ..
if i select year 2017 and month of July which is larger then currentmonth
how do i show there is not data available yet
my current code..and its not working..i'm a newbie and not sure im doing this right or not...
$mystartingyear=2017;
$mystartingmonth=01;
$currentmonth=date("m");
$currentyear=date("Y");
if ($currentyear >= $mystartingyear && $currentmonth >= $mystartingmonth)
{
echo "Show Data";
}
else
{
echo "No Data yet";
}
i also tried it like this
$mystartingyear=2017;
$mystartingmonth='01';
$currentmonth=12;
$currentyear=2017;
//$currentmonth=date("m");
//$currentyear=date("Y");
if ($currentyear >= $mystartingyear && $currentmonth >= $mystartingmonth)
{
echo "Show Data";
}
else
{
echo "No Data yet";
}
it always display "show data"
Edit:
Integers from 01 to 07 are ok just as long as you don't do 010 (with 3 integers) since that will be represented as 8. But as soon as you start hitting 08 and 09 for the months of August and September (which may be what's in your unknown dropdown), you will have problems.
So it's best you quote it.
Consult "Footnotes".
Original answer:
The leading zero in 01 for:
$mystartingmonth = 01;
^^
is treated as an octal.
It needs to be quoted:
$mystartingmonth = '01';
Octals references:
http://php.net/manual/en/language.types.integer.php
https://en.wikipedia.org/wiki/Octal
Footnotes:
If your current code is failing you, then something else is failing you.
You mention in your question that you're using this from a dropdown and that code wasn't included, nor how it's being passed.
Use PHP's error reporting, set to catch and display:
http://php.net/manual/en/function.error-reporting.php
Verify your conditional statement's logic also; both conditions must be met.
There is missing semicolon after first echo i.e. code should be
echo "Show Data";
Then every thing should work fine,
The date(); function in php returns the date in string and when you compare a string with integer it is implicitly converted into equivalent integer variable,if you want for sure you can use intvar(); function which converts variable to equivalent integer.But in your case it is not necessary.For more about i recommend you to read php manual .

Unable to get date/time from XML - Strange value in source

I'm just starting with php, but this is a thing I can't figure out.
I browsed the internet / stack / other forums, but for now I don't have any clue.
The date format is something I can't understand / recognize at all:
<datum>1491976626</datum>
<datum>1491894573</datum>
<datum>1491734853</datum>
<datum>1491680837</datum>
<datum>1491671357</datum>
Here's the link to the XML: Link
When you check the 'datum' node, you'll see it.
As an example (compared to the output on this site)
Value: 1491734853
= Date: 09-04-2017
Value: 1491671357
= Date: 08-04-2017
Value: 1491463926
= Date: 06-04-2017
Anyone of you guys / guru's have an idea how to get this working? Is there a default (sort of) algoritm for this or something I don't know of?
Thank you very much for thinking with me :)
I think this should do the job, but I'm unable to get it to show..
This is the PHP code I have so far:
<?php
foreach ($xml->beoordelingen->beoordeling as $beoordelingenoverzicht) {
echo "<div class='containerbeoordeling'><div class='hoofd'>";
foreach($beoordelingenoverzicht->voornaam as $label => $voornaam) {
echo "<div class='naam'><span id='label'>Naam</span><span id='voornaam'>{$voornaam}</span>"; }
foreach($beoordelingenoverzicht->achternaam as $label => $achternaam) {
echo "<span id='achternaam'> {$achternaam}</span></div>";
}
foreach($beoordelingenoverzicht->datum as $label => $datum) {
$datumnew = date('Y-m-d h:i:s',$datum);
echo "<div class='datum'><span id='label'>{$label}</span><span id='datum'>{$datumnew}</span></div></div>";
}
foreach($beoordelingenoverzicht->beschrijving as $label => $beschrijving) {
echo "<div class='beschrijving'>{$beschrijving}</div>";
}
echo "</div>";
}
?>
I wouldn't be surprised if I implemented it totally wrong :D
It suppose it's just a Unix timestamp, one of the most ubiquitous date formats in computer science. Many PHP date functions support it natively, e.g. date():
var_dump(date('r', 1491734853));
// string(31) "Sun, 09 Apr 2017 12:47:33 +0200"
The optional timestamp parameter is an integer Unix timestamp that
defaults to the current local time if a timestamp is not given. In
other words, it defaults to the value of time().

Need help within a loop to group data

Need some help, been going around this for ages, but just cant seem to solve it. I've got some data in a field called "Term Year PrNo". The data in this field is like below:
[2010-201110]Winter - 2010 - 1st
[2010-201111]Winter - 2010 - 2nd
[2010-201120]Spring - 2011 - 1st
[2010-201121]Spring - 2011 - 2nd
[2010-201130]Summer - 2011 - 1st
[2010-201131]Summer - 2011 - 2nd
[2011-201210]Winter - 2011 - 1st
[2011-201211]Winter - 2011 - 2nd
[2011-201220]Spring - 2012 - 1st
[2011-201221]Spring - 2012 - 2nd
[2011-201230]Summer - 2012 - 1st
[2011-201231]Summer - 2012 - 2nd
[2012-201310]Winter - 2012 - 1st
[2012-201311]Winter - 2012 - 2nd
[2012-201320]Spring - 2013 - 1st
[2012-201321]Spring - 2013 - 2nd
[2012-201330]Summer - 2013 - 1st
I need to make each row of data in that field a radio button selection, which I've managed to do by sticking the contents of the field and spitting it out as an input field. I've also used regex to clean the look of the input value - i.e. remove the first sort field. So far so good. The problem I cant seem to solve is I need to break the data down in segments and wrap them around a div class called yearblock based on the years, 2010-2011 | 2011-2012 | 2012-2013, so that I can arrange them nicely using CSS. I've managed to figure out how to start div class, by comparing previous year to current year, but I cant seem to figure out how to appropriately put the end in after echoing out my input. Hope this makes sense, can someone look at my code and point me in the right direction please?
<?php
$arrayTermdates = array();
foreach($termsResult->getRecords() as $key => $term)
{
$arrayTermdates[] = $term->getField('Term Year PrNo');
}
$arrayTermdates = array_unique($arrayTermdates);
sort($arrayTermdates, SORT_STRING | SORT_FLAG_CASE);
foreach($arrayTermdates as $termdate)
{
preg_match_all("/\[[^)]+\]/",$termdate,$matches);
$year = str_replace('[', '', $matches[0][0]);
$year = str_replace(']', '', $year);
$year = str_replace(' ', '', substr($year, 0, -2));
$termdate = preg_replace("/\[[^)]+\]/","",$termdate);
/*
/ - opening delimiter (necessary for regular expressions, can be any character that doesn't appear in the regular expression
\[ - Match an opening parenthesis
[^)]+ - Match 1 or more character that is not a closing parenthesis
\] - Match a closing parenthesis
/ - Closing delimiter
*/
if ($previousYear != $year || $previousYear == '')
{
echo '<div class="yearblock">';
echo '<strong>'.$year.'</strong><br />';
}
?>
<div class="term_value_list">
<input name="Termdate[]" type="radio" value="<?php echo $termdate; ?>">
<?php
$TermdatesArray = explode('-',$termdate);
$Termdisplay = $TermdatesArray[0].' '.$TermdatesArray[1].' ['.str_replace(' ', '', $TermdatesArray[2]).' PR]';
echo $Termdisplay;
?>
<!-- I need to echo an </div> for div class yearblock -->
You're almost there. I'm going to make a little simplification to your code to get rid of the regexp, however.
First off, we are going to initiate a year tracker. This will allow us to keep track of which year we are in.
$myCurrentYear = false;
From there, we'll loop through your rows. The first check we will do is to check if the year is different. If it is, and the current year was not false, we'll output a </div>. Then, if it was different, we'll print headers for the new year.
foreach ($arrayTermdates as $date) {
$newdate = split("-",substr($date,strpos($date,"]")+1));
// Gotta remember to trim stuff
$year = (int)trim($newdate[1]);
if ($year != $myCurrentYear) {
if ($myCurrentYear !== false) {
echo "</div>";
}
$myCurrentYear = $year;
echo "<div class='yearblock'><strong>Year ".$myCurrentYear."-".($myCurrentYear+1)."</strong>:";
}
// Do your processing here
}
// NOTE: the last one won't be closed. We'll close it here
if ($myCurrentYear !== false) {
echo "</div>";
}
Start your first div before the first output:
echo '<div class="yearblock">';
Then close the block and open a new one each time your if() condition is true:
if ($previousYear != $year || $previousYear == '')
{
echo '</div><div class="yearblock">';
echo '<strong>'.$year.'</strong><br />';
}
And finally, close the final div after you have finished creating output:
echo '</div>';

representation of any number in power of '2' using PHP

I tried to play with php,however I got stuck at one place, where I tested value of $n=1024, then it takes more than 60sec,so timeout error of php arises,I don't know how to overcome this problem,if my only requirement is to present any input number in the 20 + ---+ 2n Form.
trying below code with n=121,I got this,but I wish to represent 57 also in 2n
Form,So I tried recursion,which didn't worked.
see how a given no. be represented in powers of '2': 20 + 21 + 22 +
2 + 24+ 25 + 26+ 57
CODE:
<?php
echo("see how a given no. be represented in powers of '2' :<br/>\n");
$n=121;
$two_pow=array(
pow(2,0),pow(2,1),pow(2,2),pow(2,3),pow(2,4),pow(2,5),
pow(2,6),pow(2,7),pow(2,8),pow(2,9),pow(2,10)
);
//print_r($two_pow);
$i=0;
while($n>=$two_pow[$i])
$i++;
/* displaying 2^3*/
if($i>0)
$ij=$i-1;
/* diplaying difference of give N and 2^i*/
$diff=$n-$two_pow[$ij];
if($n>0)
{
for($i=0;$i<=$ij;$i++)
{
echo("2<sup> $i </sup>"."+ \n");
if($i==$ij && $diff>0)
{
echo("\n". $diff);
}
}
}
else
echo("<br/>not possible for values less then zero");
?>
No need for recursion or anything like that, just convert to binary and loop through the characters:
$bits = array_reverse(str_split(decbin($n)));
$output = array();
foreach($bits as $key => $bit) {
if($bit == 1) {
$output[] = '2<sup>'.($key).'</sup>';
}
}
echo implode(' + ', $output);
Working example:
http://codepad.org/plzvw2RL
Cant you use - base_convert() to convert the string to binary, then format your output based on the position of bits?
It is a joke right?
Oh it isn't?
Well ok
take look at decbin function. Isn't it easier?
You can overcome the timeout restriction by disabling the timeout:
set_time_limit(0);

Help me translate long value, expressed in hex, back in to a date/time

I have a date value, which I'm told is 8 bytes, a single "long" (aka int64) value, and converted to hex:
60f347d15798c901
How can I convert this and values like this, using PHP, into a time/date?
Converting it to decimal gives me:
96 243 71 209 87 152 201 1
A little more info: the original value is a C# DateTime, and should represent a time/date about 2 or 3 weeks ago.
I found another reference which might point to some more relevant information. In this case, a Windows date and time as used in the registry. Apparently these are also stored as 64 bit values.
This is looking a bit more helpful, as it mentions that ending in C?01 is an indicator of this type of date. Note that this is little endian (ie, most significant bytes on the right) so the bytes are in the wrong byte order for hexdec() without reversing them 2 hex digits at a time (ie, start with right-most 2 hex digits, then next two, etc).
And, according to this source,
A single tick represents one hundred nanoseconds or one ten-millionth of a second. The value of this property represents the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001, which represents.
What might trip you up is that unfortunately PHP cannot handle 64 bit integers. It maxes out at 32 bit. Floats will help, but that doesn't stop hexdec() itself from only coping with ints. So it may be complicated to do this math; you may still need to split it into two, then combine them into a float by casting the more significant value to float and multiplying it by 2^32 also cast as float. It's possible that PHP built for 64-bit hardware may not have this limitation, but I don't know for sure.
(Thanks to thomasrutter's post, which gave me the Windows filetime epoch):
The given date appears to be a Windows 64-bit little-endian file date-time,
60 f3 47 d1 57 98 c9 01,
which is equivalent to the quadword
01c99857d147f360
which as an integer is
128801567297500000
This is "the number of 100-nanosecond intervals
that have elapsed since 12:00 midnight, January 1,
1601 A.D. (C.E.) Coordinated Universal Time (UTC)"
After conversion, it gives
Thu, 26 February 2009 21:18:49 UTC
Sample code:
<?php
// strip non-hex characters
function hexstring($str) {
$hex = array(
'0'=>'0', '1'=>'1', '2'=>'2', '3'=>'3', '4'=>'4',
'5'=>'5', '6'=>'6', '7'=>'7', '8'=>'8', '9'=>'9',
'a'=>'a', 'b'=>'b', 'c'=>'c', 'd'=>'d', 'e'=>'e', 'f'=>'f',
'A'=>'a', 'B'=>'b', 'C'=>'c', 'D'=>'d', 'E'=>'e', 'F'=>'f'
);
$t = '';
$len = strlen($str);
for ($i=0; $i<$len; ++$i) {
$ch = $str[$i];
if (isset($hex[$ch]))
$t .= $hex[$ch];
}
return $t;
}
// swap little-endian to big-endian
function flip_endian($str) {
// make sure #digits is even
if ( strlen($str) & 1 )
$str = '0' . $str;
$t = '';
for ($i = strlen($str)-2; $i >= 0; $i-=2)
$t .= substr($str, $i, 2);
return $t;
}
// convert hex string to BC-int
function hex_to_bcint($str) {
$hex = array(
'0'=>'0', '1'=>'1', '2'=>'2', '3'=>'3', '4'=>'4',
'5'=>'5', '6'=>'6', '7'=>'7', '8'=>'8', '9'=>'9',
'a'=>'10', 'b'=>'11', 'c'=>'12', 'd'=>'13', 'e'=>'14', 'f'=>'15',
'A'=>'10', 'B'=>'11', 'C'=>'12', 'D'=>'13', 'E'=>'14', 'F'=>'15'
);
$bci = '0';
$len = strlen($str);
for ($i=0; $i<$len; ++$i) {
$bci = bcmul($bci, '16');
$ch = $str[$i];
if (isset($hex[$ch]))
$bci = bcadd($bci, $hex[$ch]);
}
return $bci;
}
// WARNING! range clipping
// Windows date time has range from 29000 BC to 29000 AD
// Unix time only has range from 1901 AD to 2038 AD
// WARNING! loss of accuracy
// Windows date time has accuracy to 0.0000001s
// Unix time only has accuracy to 1.0s
function win64_to_unix($bci) {
// Unix epoch as a Windows file date-time value
$magicnum = '116444735995904000';
$t = bcsub($bci, $magicnum); // Cast to Unix epoch
$t = bcdiv($t, '10000000', 0); // Convert from ticks to seconds
return $t;
}
// get input
$dtval = isset($_GET["dt"]) ? strval($_GET["dt"]) : "0";
$dtval = hexstring($dtval); // strip non-hex chars
// convert to quadword
$dtval = substr($dtval, 0, 16); // clip overlength string
$dtval = str_pad($dtval, 16, '0'); // pad underlength string
$quad = flip_endian($dtval);
// convert to int
$win64_datetime = hex_to_bcint($quad);
// convert to Unix timestamp value
$unix_datetime = win64_to_unix($win64_datetime);
?><html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Windows datetime test code</title>
</head>
<form method="get">
<label>Datetime value: <input name="dt" type="text" value="<?php echo $dtval; ?>"/></label>
<input type="submit" />
</form>
<hr />
Result:
Quad: <?php echo $quad; ?><br />
Int: <?php echo $win64_datetime; ?><br />
Unix timestamp: <?php echo $unix_datetime; ?><br />
Date: <?php echo date("D, d F Y H:i:s e", $unix_datetime); ?><br />
<body>
</body>
</html>
I believe you can convert it to a decimal int with hexdec(). That will be a timestap that you can work on with date().
The value you've given is 36 hex digits, i.e. 18 bytes-worth. That's not an Int64 converted to hex.
Go back to whoever gave you the explanation of the format and ask them to tell you the truth this time :)
EDIT: Okay, next step: find out what that number is actually meant to mean. Ticks since 1970? Millis since AD 1? Do you know what your example string is meant to represent?
If it is the same type of 64 bit hex NTP timestamp as described here, then you should be splitting the hex string equally in two, that is, imagine a separator between the first 8 hex digits and the other 8.
Convert the first half (first 32 bits' worth) into an integer with hexdec(), and this integer will be the date value in Unix timestamp format (seconds since Jan 1 1970 GMT) which you can then use in the date() function, etc.
The second part is fractional sections, useful if you need accuracy finer than one second (though not many applications do, and PHP's built in date and time functions don't except for microtime()). You would also convert this to decimal with hexdec().

Categories