Split 5 or 6 character number before fourth-last number - php

I get POST request date strings in the format of mY (no leading zeros on the month), so there's no delimiting character to split on.
Examples: 122019 or 62019
I need to separate the five or six digit string into a one or two digit month and a four digit year.
Eg1 : 122019
$a[0] = 12;
$a[1] = 2019
Eg2 : 62021
$a[0] = 6;
$a[1] = 2021

I don't know about this date format, especially about how you use an integer as a date. But let's consider that it's on purpose, the year is always gonna be 4 character, so you can just get the year by taking the last 4 char and use the rest as the month.
Using substr() see PHP.NET Substr
Return part of a string
And you can specify the start and length of the part you want to get, or using - to get character starting from the end of the string.
$weirdDate = 122019;
//takes the last 4 character
$year = substr($weirdDate , -4);
//takes the string from the beginning to 4 char before the end
$month = substr($weirdDate , 0,strlen($weirdDate)-4);
echo $year;
echo $month;
Again, it seems like a weird way to get a month/year date, but i'm answering based on the assumption that a year is gonna be 4 char long.
If it's not, you can't really split the number since the month part can be 1 or 2 char long.
09-2019 would be 92019
11-2019 would be 112019

A simple use of the substr() function will do this nicely
$in = '122019';
$year = substr($in,-4);
$month = substr($in,0, strlen($in)-4);
echo $year . ' month ' . $month;
$a[] = $month;
$a[] = $year;
RESULT
2019 month 12
array (
[0] => 12
[1] => 2019
)
Or if we use $in = '62019';
The RESULT would be
2019 month 6
array (
[0] => 6
[1] => 2019
)
Reference 'substr()`

You could also use substr with strpos. With substr(), you could first get the year by providing a negative offset to start capturing from back of the string as the year is going to be 4 digits. Then, you could use strpos() to find the index of the year and use this as the ending index to get the month.
That being said, best way to deal with this data is to either have a proper date format or better to have a JSON string with proper keys for days, month and year along with date.
Code:
<?php
$str = '122019';
$year = substr($str,-4);
$month = substr($str,0,strpos($str,$year));
echo $month," ",$year;

I have one another solution to use str_replace() with substr() like:
<?php
$string = "122019";
$year = substr($string, -4);
$date = str_replace($year, "", $string);
$myArray = array($date,$year); // convert into an array
echo "<pre>";
print_r($myArray);
?>
Desired Output:
Array
(
[0] => 12
[1] => 2019
)
Side Note: This will only work, if your year based on last 4 characters and other then these 4 characters must be date, as you mentioned in your question.

To accomplish this feat with two function calls, use negative parameters with substr() calls.
There is no reason to call strlen(), strpos(), or str_replace().
For a single call technique, use preg_split() with a lookahead pattern to ensure that no characters are consumed while exploding.
Codes: (Demo)
$mY = '62021';
var_export([
substr($mY, 0, -4), // month
substr($mY, -4) // year
]);
echo "\n---\n";
var_export(
preg_split('/(?=\d{4}$)/', $mY)
);

Related

Splitting strings through php to query mysql

I need to split a string in two so I can do a SELECT query in my DB. For example, I have the number '0801'. I need to split that number into '08' and '01'. How do I manage to do that?
This is easy to do using the substr() function, which lets you pull out parts of a string. Given your comment that you always have a four-digit number and want it split into two two-digit numbers, you want this:
$input = "0801";
$left = substr($input, 0, 2);
$right = substr($input, 2);
echo "Left is $left and right is $right\n";
According to your comment
The first 2 numbers. It's allways a 4 digit number and I allways need
to split it in 2 two digit numbers
You can simply use
$value = '0801';
$split = str_split($value, 2);
var_dump($split[0]);
var_dump($split[1]);
Just keep in mind $value variable should always be of a string type, not int.
you can use str_split and list
$str = '0801';
list($first,$second) = str_split($str,2);
echo $first;
// 08
echo $second;
// 01
No one gave a MySQL answer yet...
If you're selecting that number..
SELECT
SUBSTR(colname, 0, 2) as firstpart,
SUBSTR(colname, 2, 2) as secondpart
FROM table

With a simple String In Date

Myself I have such a string
citation
2d6h8y4m
d - days
min - min
h - h
y - years
m - months
s - seconds
I would like to add today's date as saved time , ie
2 days , 6 hours, 8 years and 4 months
I know how to do it in a simple way - the loop on all the text and read in sequence numbers, but my guess is that it can be done more simply - a regex . Sorry sag on this if someone gave me such a function or somehow me clues (eg . Given pattern on one character) enough , I can Narratives
#INFO
Not understood still to drive not want to do today's date to add eg 2 days , 4 months , etc.
Ie today is 2014-11-22 5:43:45 p.m.
After the addition of I 2 days 6 hours 8 years and 4 months I have
2022-04-24 11:43:45 p.m.
Separate int values & char/word by preg_match_all(). Create and array() that contains the full meaning of character (ie, h = hours). Then just foreach(). Example:
$avr = array('d'=>'days', 'min'=>'min','h'=>'hours', 'y'=>'years', 'm'=>'months', 's'=>'seconds');
$str = '2d6h8y4m';
preg_match_all('/\d+/', $str, $int);
preg_match_all('/[a-z]+/', $str, $word);
$len = count($int[0]) - 1;
$result = '';
foreach($int[0] as $k=>$v){
if($len == $k){
$result .= ' and ' . $v . ' ' . $avr[$word[0][$k]];
}else{
$suf = ($k == 0) ? '' : ', ';
$result .= $suf . $v . ' ' . $avr[$word[0][$k]];
}
}
echo $result;
Output:
2 days, 6 hours, 8 years and 4 months
The regex you're looking for is
(\d+)d(\d+)h(\d+)y(\d+)m
\d matches any digit. From this you can extract what was matched between the brackets. Here is the full code:
preg_match("(\d+)d(\d+)h(\d+)y(\d+)m", "2d6h8y4m", $matches);
Now $matches will be an array containing what is matched between the brackets. $matches[0] will be the first bracket (the day), $matches[1] will be the first bracket (the hour), etc.
Why are you reinventing the wheel?
Why don't you store intervals in ISO-8601 duration format, like for example: P8Y5M2DT6H ?
$date = new DateTime();
$interval = new DateInterval('P8Y5M2DT6H');
$date->add($interval);
demo

Check whether day is specified in a date string

Test case scenario - User clicks on one of two links: 2012/10, or 2012/10/15.
I need to know whether the DAY is specified within the link. I am already stripping the rest of the link (except above) out of my URL, am I am passing the value to an AJAX request to change days on an archive page.
I can do this in either JS or PHP - is checking against the regex /\d{4}\/\d{2}\/\d{2}/ the only approach to seeing if the day was specified or not?
You can also do this if you always get this format: 2012/10 or 2012/10/15
if( str.split("/").length == 3 ) { }
But than there is no guaranty it will be numbers. If you want to be sure they are numbers you do need that kind of regex to match the String.
You could explode the date by the "/" delimiter, then count the items:
$str = "2012/10";
$str2 = "2012/10/5";
echo count(explode("/", $str)); // 2
echo count(explode("/", $str2)); // 3
Or, turn it into a function:
<?php
function getDateParts($date) {
$date = explode("/", $date);
$y = !empty($date[0]) ? $date[0] : date("Y");
$m = !empty($date[1]) ? $date[1] : date("m");
$d = !empty($date[2]) ? $date[2] : date("d");
return array($y, $m, $d);
}
?>
I would personally use a regex, it is a great way of testing this sort of thing. Alternatively, you can split/implode the string on /, you will have an array of 3 strings (hopefully) which you can then test. I'd probably use that technique if I was going to do work with it later.
The easiest and fastest way is to check the length of the string!
In fact, you need to distinguish between: yyyy/mm/dd (which is 10 characters long) and yyyy/mm (which is 7 characters).
if(strlen($str) > 7) {
// Contains day
}
else {
// Does not contain day
}
This will work EVEN if you do not use leading zeros!
In fact:
2013/7/6 -> 8 characters (> 7 -> success)
2013/7 -> 6 characters (< 7 -> success)
This is certainly the fastest code too, as it does not require PHP to iterate over the whole string (as using explode() does).

Custom date and number format string (with padding and offsets)

I tried to create a customizable number according to a defined mask.
This is my rules to make a mask
You may enter any numbering mask. In this mask, the following tags could be used: {000000} corresponds to a number which will be incremented on each customer.
Enter as many zeros as the desired length of the counter.
The counter will be completed by zeros from the left in order to have as many zeros as the mask.
{000000+000} same as previous but an offset corresponding to the number to the right of the + sign is applied starting on first .
{000000#x} same as previous but the counter is reset to zero when month x is reached (x between 1 and 12).
If this option is used and x is 2 or higher, then sequence {yy}{mm} or {yyyy}{mm} is also required.
{dd} day (01 to 31).
{mm} month (01 to 12).
{yy}, {yyyy} or {y} year over 2, 4 or 1 numbers.
All other characters in the mask will remain intact.
Spaces are not allowed.
Example on customer created on 2007-03-01:
ABC{yy}{mm}-{000000} will give ABC0701-000099,
{0000+100}-ZZZ/{dd}/XXX will give 0199-ZZZ/31/XXX
So my current mask is C{000000}
<?php
$mask = "C{000000}";
$number = 100;
if (preg_match('/\{(0+)([#\+][0-9]+)?([#\+][0-9]+)?\}/i',$mask,$regType)){
$masktype=$regType[1];
$masktype_value=substr(preg_replace('/^TE_/','',$number),0,strlen($regType[1]));//get n first characters of code where n is length in mask
$masktype_value=str_pad($masktype_value,strlen($regType[1]),"#",STR_PAD_RIGHT);
$maskwithonlyymcode=$mask;
$maskwithonlyymcode=preg_replace('/\{(0+)([#\+][0-9]+)?([#\+][0-9]+)?\}/i',$regType[1],$maskwithonlyymcode);
$maskwithonlyymcode=preg_replace('/\{dd\}/i','dd',$maskwithonlyymcode);
$maskwithonlyymcode=preg_replace('/\{(c+)(0*)\}/i',$maskrefclient,$maskwithonlyymcode);
$maskwithonlyymcode=preg_replace('/\{(t+)\}/i',$masktype_value,$maskwithonlyymcode);
$maskwithnocode=$maskwithonlyymcode;
$maskwithnocode=preg_replace('/\{yyyy\}/i','yyyy',$maskwithnocode);
$maskwithnocode=preg_replace('/\{yy\}/i','yy',$maskwithnocode);
$maskwithnocode=preg_replace('/\{y\}/i','y',$maskwithnocode);
$maskwithnocode=preg_replace('/\{mm\}/i','mm',$maskwithnocode);
print "maskwithonlyymcode=".$maskwithonlyymcode." maskwithnocode=".$maskwithnocode."\n<br>";
}
?>
But it is not working it is printing
maskwithonlyymcode=C000000 maskwithnocode=C000000
My desired output is C000001 - C000100.
What is missing in this code?
I do not understand your code much, so I was not able to fix it, but what about:
<?
function process_mask($mask, $number, $date)
{
while (preg_match("/\{(.+?)\}/", $mask, $match))
{
$outter_code = $match[0];
$inner_code = $match[1];
if (preg_match("/^(0+)(\+(\d+))?$/", $inner_code, $match2))
{
$number2 = $number;
if (!empty($match2[3]))
{
$number2 += intval($match2[3]);
}
$replacement = str_pad($number2, strlen($match2[1]), "0", STR_PAD_LEFT);
}
else
{
switch ($inner_code)
{
case "dd":
$replacement = date("d", $date);
break;
case "mm":
$replacement = date("m", $date);
break;
case "y":
$replacement = substr(date("Y", $date), 3);
break;
case "yy":
$replacement = date("y", $date);
break;
case "yyyy":
$replacement = date("Y", $date);
break;
default:
trigger_error("Unrecognised code $inner_code");
return NULL;
}
}
$mask = str_replace($outter_code, $replacement, $mask);
}
return $mask;
}
function test_mask($mask)
{
$date = mktime(0, 0, 0, 4, 19, 2013);
echo str_pad($mask, 25)." => ".process_mask($mask, 100, $date)."\n";
}
test_mask("C{000}");
test_mask("C{000000}");
test_mask("C{000000+10}");
test_mask("ABC{yy}{mm}-{000000}");
test_mask("{0000+100}-ZZZ/{dd}/XXX");
?>
Outputs:
C{000} => C100
C{000000} => C000100
C{000000+10} => C000110
ABC{yy}{mm}-{000000} => ABC1304-000100
{0000+100}-ZZZ/{dd}/XXX => 0200-ZZZ/19/XXX
I absolutely do not undertand your rules about resetting counters. Based on what date do you want to reset the numbers? Current date? Do you keep some counter per customer (you have not explained what the number is)? Why resetting it on certain month? Wouldn't it be more meaningful to reset it in intervals? Like every month (implementation-wise, it would make sense then to keep separate counter for every month, so that the formatting logic is current time-independent). Some example may help understanding this.
Also for date formatting, I would suggest you to stick with PHP date formatting and do not invent your own.
I would suggest you to use pattern like this instead (It's actually bit .NET-like):
{(#[+offset]|php-date-format-string)[:length]}
So (for number = 999 and date = 2013-04-19):
C{#:4} => C0999
C{#+10:4} => C1009
C{#:6} => C000999
C{#:4}/{Y} => C0999/2013
C{#:4}/{Y:4} => C0999/2013
C{#:4}/{Y:2} => C0999/13
C{#:4}/{Y:1} => C0999/3
C{#:4}/{m} => C0999/03
C{#:4}/{Y}{m} => C0999/201303
C{#:4}/{Ym} => C0999/201303
Code for this would be way simpler, more extensible and flexible.

Credit card Formatting function in Yii

I want to format the credit cards like below when i display it,
Eg:
1234 4567 9874 1222
as
1xxx xxxx xxx 1222
Is there any formatting function like this in Yii ?
No - but there's nothing wrong with using straight PHP.
If you always want the 1st and the last 4 chars you can do something like this:
$last4 = substr($cardNum, -4);
$first = substr($cardNum, 0, 1);
$output = $first.'xxx xxxx xxxx '.$last4;
There are many ways to do this, nothing Yii specific
You could do it using str_split (untested):
$string = "1234 4567 1234 456";
$character_array = str_split($string);
for ($i = 1; $i < count($character_array) - 4; $i++) {
if ($character_array[$i] != " "){
$character_array[$i] = "x";
}
}
echo implode($character_array);
So we are creating an array of characters from the string called
$character_array.
We are then looping thru the characters (starting from position 1,
not 0, so the first character is visible).
We loop until the number of entries in the array minus 4 (so the last
4 characters are not replaced) We replace each character in the loop
with an 'x' (if it's not equal to a space)
We the implode the array back into a string
And you could also use preg_replace :
$card='1234 4567 9874 1222';
$xcard = preg_replace('/^([0-9])([- 0-9]+)([0-9]{4})$/', '${1}xxx xxxx xxxx ${3}', $card);
This regex will also take care of hyphens.
There is no in-built function in Yii.

Categories