2013-04-08 6 views
5

Je veux calculer tous les dimanches entre deux dates données. J'ai essayé le code suivant. Cela fonctionne bien si les jours sont moins mais si j'entre plus de jours. Il maintient le traitement et le temps d'exécution maximum dépasse i a changé l'heure mais il continue même le traitement même le temps d'exécution est 200sec.calculer les dimanches entre deux dates

Code

est

<?php 
$one="2013-01-01"; 
$two="2013-02-30"; 

$no=0; 
for($i=$one;$i<=$two;$i++) 
{ 

    $day=date("N",strtotime($i)); 
    if($day==7) 
    { 
    $no++; 
    } 
} 
echo $no; 

?> 

s'il vous plaît aider.

+0

Pouvez-vous utiliser une boucle sur une chaîne de date comme ça? – andrewsi

+0

Vous ne pouvez pas incrémenter une chaîne comme celle-ci. Regardez comment les autres le font: http://stackoverflow.com/search?q=php+number+of+sundays –

+0

Est-ce pour un [projet euler problème (19)] (http://projecteuler.net/problem=19)? – HamZa

Répondre

25

La réponse de John Conde est correct, mais voici une solution plus efficace et mathy:

$start = new DateTime('2013-01-06'); 
$end = new DateTime('2013-01-20'); 
$days = $start->diff($end, true)->days; 

$sundays = intval($days/7) + ($start->format('N') + $days % 7 >= 7); 

echo $sundays; 

Permettez-moi de le décomposer pour vous.

$start = new DateTime('2013-01-06'); 
$end = new DateTime('2013-01-20'); 

D'abord, créer des objets DateTime, qui sont des objets puissants PHP intégré signifiait exactement pour ce genre de problème.

$days = $start->diff($end, true)->days; 

Ensuite, utilisez DateTime::diff pour trouver la différence de $start à $end (en passant true ici comme second paramètre assure que cette valeur est toujours positive), et obtenir le nombre de jours entre eux.

$sundays = intval($days/7) + ($start->format('N') + $days % 7 >= 7); 

Voici le grand - mais ce n'est pas si compliqué, vraiment. Tout d'abord, nous savons qu'il y a un dimanche pour chaque semaine, donc nous avons au moins $days/7 les dimanches pour commencer, arrondis au int avec intval.

En plus de cela, il pourrait y avoir un dimanche dans un laps de temps de moins d'une semaine; par exemple, du vendredi au lundi de la semaine suivante contient 4 jours; l'un d'eux est un dimanche. Donc, en fonction du moment où nous commençons et finissons, il pourrait y en avoir un autre. Cela est facile à expliquer:

  • $start->format('N') (voir DateTime::format) nous donne la ISO-8601 jours de la semaine pour la date de début, qui est un nombre de 1 à 7 (1 est le lundi 7 est dimanche) .
  • $days % 7 nous donne le nombre de jours restants qui ne se divisent pas uniformément en semaines.

Si notre jour de départ et le nombre de jours restants totalisent 7 ou plus, alors nous avons atteint un dimanche. Sachant cela, il suffit d'ajouter cette expression, ce qui nous donnera 1 s'il est vrai ou 0 s'il est faux, puisque nous l'ajoutons à une valeur int.

Et voilà! L'avantage de cette méthode est qu'elle ne nécessite pas d'itération tous les jours entre les temps donnés et de vérifier si c'est un dimanche, ce qui vous permettra d'économiser beaucoup de calcul, et aussi vous fera paraître vraiment intelligent. J'espère que cela pourra aider!

+2

Cette partie n'est pas vraie 'Puisque $ days et 7 sont tous deux des valeurs int, elles seront toujours arrondies à l'entier le plus proche. Vous devez utiliser une fonction ronde comme [floor()] (http://www.php.net/manual/fr/function.floor.php) pour l'arrondir, PHP ne le fera pas pour vous, essayez par exemple '$ end = new DateTime ('2013-02-20');' et la sortie sera décimale. – HamZa

+2

Vous avez absolument raison, whoops! J'ai oublié de parler de PHP pendant une seconde. –

+1

+1 pour l'approche intelligente et l'expliquer en détail. –

8
<?php 
$no = 0; 
$start = new DateTime('2013-01-01'); 
$end = new DateTime('2013-04-30'); 
$interval = DateInterval::createFromDateString('1 day'); 
$period = new DatePeriod($start, $interval, $end); 
foreach ($period as $dt) 
{ 
    if ($dt->format('N') == 7) 
    { 
     $no++; 
    } 
} 
echo $no; 

See it in action

+0

merci. Ça marche. donc ça ne fonctionnait pas parce que la chaîne n'était pas incrémentée correctement? –

+0

Fondamentalement oui. Travailler avec des chaînes de caractères, en particulier des dates, est préférable d'utiliser des fonctionnalités conçues pour cela. DateTime est conçu spécifiquement pour travailler avec des dates et comme vous pouvez le voir, il est facile à faire. –

+0

oui c'est le cas. Merci. –

0

Voici une solution si vous voulez les dimanches dans une plage de dates spécifique.

function dateRange($begin, $end, $interval = null) 
{ 
    $begin = new DateTime($begin); 
    $end = new DateTime($end); 

    $end = $end->modify('+1 day'); 
    $interval = new DateInterval($interval ? $interval : 'P1D'); 

    return iterator_to_array(new DatePeriod($begin, $interval, $end)); 
} 

/* define date range */ 
$dates = dateRange('2018-03-01', '2018-03-31'); 

/* define weekdays */ 
$weekends = array_filter($dates, function ($date) { 
    $day = $date->format("N"); 
    return $day === '6' || $day === '7'; 
}); 

/* weekdays output */ 
foreach ($weekends as $date) { 
    echo $date->format("D Y-m-d") . "</br>"; 
} 

/* define sundays */ 
$sundays = array_filter($dates, function ($date) { 
    return $date->format("N") === '7'; 
}); 

/* sundays output */ 
foreach ($sundays as $date) { 
echo $date->format("D Y-m-d") . "</br>"; 
} 

/* define mondays */ 
$mondays = array_filter($dates, function ($date) { 
return $date->format("N") === '1'; 
}); 

/* mondays output */ 
foreach ($mondays as $date) { 
echo $date->format("D Y-m-d") . "</br>"; 
} 

il suffit de changer le numéro de tous les jours que vous voulez dans votre sortie:

Monday = 1 
Tuesday = 2 
Wednesday = 3 
Thursday = 4 
Friday = 5 
Saturday = 6 
Sunday = 7 
Questions connexes