PHP Julian Date for JDE Oracle

223 Views Asked by At

i'm trying to convert a date like 2022-08-09 to a julian date for send it to JDE. The problem is that default php functions like juliantojd() return a different result. The result i expected was something like this

https://nimishprabhu.com/tools/jde-julian-date-converter-online.html

I got this function from a very old code that is doing the job in .asp

function data_giuliana(d){
var pad = "000";

var anno = String(d.getFullYear()).substr(2,2);

var timestmp     = new Date().setFullYear(d.getFullYear(),0,1);
var yearFirstDay = Math.floor(timestmp / 86400000);
var today        = Math.ceil((d.getTime()) / 86400000);
var giorno       = String(today - yearFirstDay);

giorno = pad.substring(0, pad.length - giorno.length) + giorno;

data_giuliana = "1" + anno + giorno;

return data_giuliana;}

I'm trying to convert this function in PHP for use it in my laravel application:

        function data_giuliana($test)
    {
        $pad = "000";
    
        $anno = Carbon::now()->format('Y-m-d');
    
        $timestammp     = Carbon::now()->timestamp;
        $yearFirstDay = floor($timestammp / 86400000);
        $today        = ceil(Carbon::now()->toDateTimeString() / 86400000);
        $giorno       = ($today - $yearFirstDay);
    
      $giorno = substr($pad, strlen($pad) - strlen($giorno)) . $giorno;
    
      $data_giuliana = "1" . $anno . $giorno;
    
      return $data_giuliana;
      dd($data_giuliana);
    }

But it's not working.

Does somebody know any function for php? Or at least help me to convert properly the up function? Thanks a lot

3

There are 3 best solutions below

5
aynber On BEST ANSWER

There's a few things that you have to tweak for javascript vs PHP. For instance, javascript uses milliseconds while PHP does not. So you need to divide by 86400, not 86400000, and this also makes the padding unnecessary. You're also trying to append and divide using string dates instead of timestamps, which throws it off. So changing the divisors, fixing the timestamps, and also changing $anno so it only gets the last 2 digits of the year fixes the code like this:

function data_giuliana($date = null)
{
    $cdate = $date ? Carbon::parse($date) : Carbon::now();
    $anno = $cdate->format('y'); // 2 digit year

    $timestamp = $cdate->copy()->firstOfYear()->timestamp;
    $yearFirstDay = floor($timestamp / 86400);
    $today = ceil($cdate->timestamp / 86400);
    $giorno = ($today - $yearFirstDay);

    $data_giuliana = "1" . $anno . $giorno;

    return $data_giuliana;
}

After reading up on what a Julian date is, you can do this much easier with Carbon. z gets the day of the year, starting from 0, so you just need to add 1 to it, and start the format with 1.

echo Carbon::now()->format('1yz')+1; // 122221
1
AudioBubble On

Final result for a JDE Oracle julian date:

           function data_giuliana($date = null)
    {   

        $date_parse = Carbon::parse($date);
        $date_now = Carbon::now();

        if($date) {
            $anno = $date_parse->format('y'); // 2 digit year
    
            $timestamp = $date_parse->copy()->firstOfYear()->timestamp;
            $yearFirstDay = floor($timestamp / 86400);
            $today = ceil($date_parse->timestamp / 86400);
            $giorno = ($today - $yearFirstDay + 1); // aggiunto +1
            dump($giorno);

            if($giorno < 100 && $giorno < 10) {
                $data_giuliana = "1" . $anno . '00' . $giorno;  
                return $data_giuliana;
            }
            if($giorno < 100) {
                $data_giuliana = "1" . $anno . '0' . $giorno;  
                return $data_giuliana;
            } else {
                $data_giuliana = "1" . $anno . $giorno; 
                return $data_giuliana;
            }
        } else {

            $anno = $date_now->format('y'); // 2 digit year
        
            $timestamp = $date_now->copy()->firstOfYear()->timestamp;
            $yearFirstDay = floor($timestamp / 86400);
            $today = ceil($date_now->timestamp / 86400);
            $giorno = ($today - $yearFirstDay); 
        
            $data_giuliana = "1" . $anno . $giorno;
        
            return $data_giuliana;
        }
    }

If the $date is not passed as the param the function will go to the else condition and will get the timestamp.

Ex: 22/08/2022 = 122234

2
blhylton On

Problem with the Accepted Answer

The accepted answer is, unfortunately, incorrect. The JDE Julian date is always six digits and does not always start with "1". To see an example, change the year to anything in the 1900s.

1999-08-09 = 099221 per https://nimishprabhu.com/tools/jde-julian-date-converter-online.html

Carbon::parse('1999-08-09')->format('1yz')+1; // 199221

Additionally, it falls apart with dates in the first 100 days of the year, because the 'z' format isn't going to pad the left with zeroes.

Carbon::parse('2022-01-10')->format('1yz')+1; // 1230

Answer to the Original Question

The built-in juliantojd(...) function returns the value for a classic Julian date, which is an entirely different thing than the JDE Julian date. JDE format is CYYDDD which is century, year, and day of the year, respectively. The century starts with 19xx = 0, so we need to compute the first digit.

function data_giuliana($year, $month, $day){
    $date_obj = (new \DateTime())->setDate($year, $month, $day);
    
    // Year and Day of Year are easy to get
    $year = $date_obj->format('y');
    // Keep in mind that PHP date of year starts at 0, but JDE starts at 1
    $day = $date_obj->format('z') + 1;
    
    // For Century, we take the full year, subtract the year we found already,
    // subtract 1900 (since, with JDE, 1900 = 0) and then divide by 100 so that
    // the century 2xxx is 1, not 100.
    $full_year = $date_obj->format('Y');
    $century = ($full_year - $year - 1900) / 100;

    // Now we can just piece it together.
    return $century 
        . str_pad($year, 2, '0', STR_PAD_LEFT) 
        . str_pad($day, 3, '0', STR_PAD_LEFT);
}

You could also do this with Carbon, which reduces the code substantially.

function data_giuliana($date){
    $date_obj = Carbon::parse($date);
    // Using floor here rather than subtracting the short year has the same effect
    $century = floor(($date_obj->year - 1900) / 100);

    return $century 
        . $date_obj->format('y')
        . str_pad($date_obj->dayOfYear, 3, '0', STR_PAD_LEFT);
}