I'd be interested to see the eloquent solution I'm sure someone already has waiting... but part of me sees this as a sort of state-machine type problem that parses through the format string in one go, using the first character of the special format identifiers as a key. For example, with the format string you have there, you start at the left and work until the end. You encounter a 'y', so you see how many y's you have in a row and consume as many as you can.
I was bored, so I came up with this (long, ugly) code:
<?php
// return number of consectutive $char's in $string starting at $offset
function numConsChars( $char, $string, $offset, $max )
{
if( $string[ $offset ] != $char )
{
return 0;
}
else
{
for( $num = 0;
( ( $num <= $max )
&& ( $offset < strlen( $string ) )
&& ( $string[ $offset ] == $char ) );
$num++, $offset++
);
return $num;
}
}
function _date_format( $fmt )
{
$ret = '';
for( $i = 0; $i < strlen( $fmt ); )
{
// longest format string is 4 ('yyyy')
$num = numConsChars( $fmt[ $i ], $fmt, $i, 4 );
switch( $fmt[ $i ] )
{
case 'y':
if( $num == 4 )
{
$ret .= date( 'Y' );
$i += 4;
}
else if( $num == 2 )
{
$ret .= date( 'y' );
$i += 2;
}
else
{
$ret .= 'y';
$i++;
}
break;
case 'm':
if( $num == 2 )
{
$ret .= date( 'm' );
$i += 2;
}
else
{
$ret .= date( 'n' );
$i++;
}
break;
case 'M':
if( $num == 2 )
{
$ret .= date( 'F' );
$i += 2;
}
else
{
$ret .= date( 'M' );
$i++;
}
break;
case 'D':
if( $num == 2 )
{
$ret .= date( 'l' );
$i += 2;
}
else
{
$ret .= date( 'D' );
$i++;
}
break;
case 'd':
if( $num == 2 )
{
$ret .= date( 'd' );
$i += 2;
}
else
{
$ret .= date( 'j' );
$i++;
}
break;
default:
$ret .= $fmt[ $i ];
$i++;
break;
}
}
return $ret;
}
echo _date_format( 'yyyy-yy-MM-M-mm-m-DD-D-dd-d' );
which outputs this:
2013-13-December-Dec-12-12-Monday-Mon-02-2
(Yes, I realize the objective was to utilize Javascript, but I prototype random ideas faster in PHP, so sue me. 🙂)