Datumsrechnerei :-)

HeinerK

Erfahrenes Mitglied
Moin,

ich habe einen String, der Kalenderwoche und und Jahr enthält. Sieht so aus: "04-12", also kw04 in 2012.

Wie kann ich daraus die Folgewoche im selben Format, also "05-12", berechnen? :-)

Muss halt auch Wochen um den Jahreswechsel herum korrekt abdecken.

Danke :-)
 
Hi,

1.) String splitten
PHP:
$parts = explode('-', $yourString);

2.) $parts[0] enthält nun 4 und $parts[1] enthält nun 12.

3.) Ersten Wert erhöhen:
PHP:
$parts[0]++;

4.) Wieder zusammenfügen
PHP:
$yourString = $parts[0] . '-' . $parts[1];

Wenn du führende Nullen brauchst:
PHP:
$parts[0] = str_pad($parts[0], 2, '0', STR_PAD_LEFT);
$parts[1] = str_pad($parts[1], 2, '0', STR_PAD_LEFT);

$yourString = $parts[0] . '-' . $parts[1];

PS: Den Jahreswechsel habe ich jetzt nicht aufgeführt, allerdings denk ich mal, dass du das auch allein mit ein paar if-Bedingungen schaffst ;) Kannst ja fragen, wenn du nicht weiterkommst.
 
Hehe. So hab ich das in den letzten 5 min auch zusammengestückelt. :-)

Jahreswechsel "mit ein paar if-Bedingungen" ist aber bissl schwierig. Die Jahre haben ja verschiedene Wochenanzahlen (2014 z.B. 52 Kalenderwochen während 2015 53 Kalenderwochen hat). Oder denke ich da zu kompliziert?

Hatte gehofft, dass ich meinen String irgendwie in ein "richtiges Datumsformat" bekommen und es dann PHP überlassen kann sich Gedanken über diese ekelige "wie viele KW hat das Jahr"-Geschichte zu machen.
 
Die date-Funktionen sind Dein Freund. Timestamp als Basis aller Datumsberechnungen ist stets eine gute Wahl. Mit strtotime() bzw. mktime() nach timestamp, mit date() wieder zurück. Man darf nicht vergessen, dass Kalenderwochen überlappend sind. Im Jahr 2013 endet KW52 am 29.12. und am 30.12.2013 beginnt KW01 2014.

strtotime() - http://selfphp.de/funktionsreferenz/datums_und_zeit_funktionen/strtotime.php
mktime() - http://selfphp.de/funktionsreferenz/datums_und_zeit_funktionen/mktime.php
date() - http://www.selfphp.de/funktionsreferenz/datums_und_zeit_funktionen/date.php

Wurde hier vor ~6 Jahren besprochen :)
http://www.tutorials.de/php/297102-timestamp-aus-kw-wochentag-und-jahr-bilden.html

mfg chmee
 
Habe gerade hier eine Lösung für dich gefunden: http://stackoverflow.com/a/3319413/603003
PHP:
function getNumberOfWeeksInYear($year) {
  return int_val(gmdate("W", strtotime("31 December $year")));
}
Hallo,
diese Funktion funktioniert nur wenn der 31. Dezember des betreffenden Jahres auf ein Donnerstag, Freitag, Sonnabend oder Sonntag fällt. In diesem Jahr fällt der 31. Dezember auf einen Dienstag und mit der Funktion erhält man "1" als Ergebnis.

Aber es gibt eine Regel, die sich einfach umsetzen lässt:
Ein Jahr hat 53 Wochen, wenn es an einem Donnerstag beginnt UND auch an einem Donnerstag endet, ansonsten hat es 52 Wochen.

Korrektur:
Tut mir leid, habe gerade noch mal nachgesehen und bemerkt, dass o.g. Regel bei den Schaltjahren nicht funktioniert. Schaltjahre (366 Tage) haben 53 Wochen wenn sie an einem Donnerstag beginnen ODER an einem Donerstag enden. Da ein normales Jahr (365 Tage) ohnehin am gleichen Wochentag beginnt und auch endet kann diese Regel verallgemeinert werden:
Ein Jahr hat 53 Wochen, wenn es an einem Donnerstag beginnt ODER auch an einem Donnerstag endet, ansonsten hat es 52 Wochen.​
 
Zuletzt bearbeitet:
Probiere es mal so:
PHP:
function formatWeek ($string) {
  if (sscanf($string, '%d-%d', $week, $year) !== 2) {
    return false;
  }

  if ($week === (int) date('W', mktime(0, 0, 0, 1, 1, $year + 1))) {
    return sprintf('%d-%d', 1, $year + 1);
  } else {
    return sprintf('%d-%d', $week + 1, $year);
  }
}

Nachtrag: Mir ist gerade aufgefallen, dass meine Lösung nicht so ganz funktioniert. Daher habe ich hier eine funktionierende Lösung gebastelt, die ermittelt, ob ein Jahr 53 oder 52 Wochen hat:
PHP:
function year_has_53_weeks ($year) { 
  $first = (int) date('N', mktime(0, 0, 0,  1,  1, $year));
  $last  = (int) date('N', mktime(0, 0, 0, 12, 31, $year));

  return (($first === 4 and ($last === 4 or $last === 5)) or ($first === 3 and $last === 4));
}

# und die eigentliche Funktion
function formatWeek ($string) {
  if (sscanf($string, '%d-%d', $week, $year) !== 2) {
    return false;
  }

  if (year_has_53_weeks($year) xor $week === 52) {
    return sprintf('%d-%d', 1, $year + 1);
  } else {
    return sprintf('%d-%d', $week + 1, $year);
  }
}
 
Zuletzt bearbeitet:
Danke für Eure Antworten. Klappt. :-)

PHP:
   //$week_before = explode("-", $label_x[$j-1]); 
   
   // For testing: 2015 has 53 weeks; 2014 has 52
   $week_before[0] = '52';
   $week_before[1] = '15';
   
   echo '$week_before[0] = '.$week_before[0].' // week<br> ';
   echo '$week_before[1] = '.$week_before[1].' // year<br><br>';
   
   if ($week_before[0] < 52) {
    $week = str_pad(($week_before[0] + 1),2,'0',STR_PAD_LEFT);
    $year = str_pad(($week_before[1]),2,'0',STR_PAD_LEFT);
   }
   elseif ($week_before[0] == 52) {
    // is it a 53-week year? this is only the case if the fist AND the last day are Thursdays.
    $first_day = mktime(0, 0, 0, 1, 1, '20'.$week_before[1]);
    $last_day = mktime(0, 0, 0, 12, 31, '20'.$week_before[1]);
    
    /*print date("Y-m-d H:i:s", $first_day)." --> ";
    print date("N", $first_day);
    print '<br>';
    print date("Y-m-d H:i:s", $last_day)." --> ";
    print date("N", $last_day);*/
    
    if ((date("N", $first_day) == 4) AND (date("N", $first_day) == 4)) {
     $week = '53';
     $year = str_pad(($week_before[1]),2,'0',STR_PAD_LEFT);
    }
    else {
     $week = '01';
     $year = str_pad(($week_before[1] + 1),2,'0',STR_PAD_LEFT);
    }
   }
   elseif ($week_before[0] == 53) {
    $week = '01';
    $year = str_pad(($week_before[1] + 1),2,'0',STR_PAD_LEFT);
   }
   else {
    die("error in week computation");
   }
   echo '$week = '.$week.'<br>';
   echo '$year = '.$year;
   
   die();
 
Ich habe übrigens noch eine wesentlich schönere Lösung gefunden:
PHP:
date('W', mktime(0, 0, 0, 12, 28, $year)) === '53';
 
'Nen kleiner Copy&Paste-Fehler war bei mir auch noch drin. Muss natürlich

PHP:
if ((date("N", $first_day) == 4) AND (date("N", $last_day) == 4)) {

heißen.
 
Zurück