2009-05-29 25 views
10

Estoy intentando escribir una función de calendario como ésteObtener el primero o el último viernes en un mes

function get_date($month, $year, $week, $day, $direction) 
{ 
    .... 
} 

$week es un entero (1, 2, 3 ...), es un día $ día (dom, lunes, ...) o número, lo que sea más fácil. La dirección es un poco confusa, porque hace un cálculo diferente.

Por ejemplo, vamos a llamar a

get_date(5, 2009, 1, 'Sun', 'forward');

Utiliza el valor por defecto, y se pone el primer domingo de mayo es decir, 2009-05-03. Si llamamos

get_date(5, 2009, 2, 'Sun', 'backward');

, devuelve el segundo domingo pasado en mayo es decir, 2009-05-24.

+0

Solo por el bien de la curiosidad ... ¿Para qué lo estás usando? No es tan simple, pero se puede hacer de todos modos. – MartinodF

+0

Estoy escribiendo un programador de trabajos. Algunos de los puestos son mensuales, y necesito poder determinar en qué fechas mostrarlos en el calendario. – Zahymaka

+0

¡Lo escribió para usted, espero que funcione como esperaba! – MartinodF

Respuesta

12

Quizás se puede hacer más rápido ...
Esto fue MUY interesante para codificar.

Tenga en cuenta que es $direction 1 para adelante y para atrás -1 para facilitar las cosas :)
Además, $day comienza con un valor de 1 para el lunes y termina a las 7 para el domingo.

function get_date($month, $year, $week, $day, $direction) { 
    if($direction > 0) 
    $startday = 1; 
    else 
    $startday = date('t', mktime(0, 0, 0, $month, 1, $year)); 

    $start = mktime(0, 0, 0, $month, $startday, $year); 
    $weekday = date('N', $start); 

    if($direction * $day >= $direction * $weekday) 
    $offset = -$direction * 7; 
    else 
    $offset = 0; 

    $offset += $direction * ($week * 7) + ($day - $weekday); 
    return mktime(0, 0, 0, $month, $startday + $offset, $year); 
} 

Lo he probado con algunos ejemplos y parece que funciona siempre, asegúrese de que compruebe que aunque;)

+0

Ah, y también tenga en cuenta que el lunes = 1, el domingo = 7 – MartinodF

2

Puede utilizar mktime para recuperar la marca de tiempo Unix del primer día del mes:

$firstOfMonth = mktime(0, 0, 0, $month, 1, $year); 

Cuando se tiene la fecha del primer día de un mes determinado que es fácil de recuperar el día de la semana para esa fecha utilizando date:

$weekday = date("N", $firstOfMonth); 

Desde allí es más fácil simplemente dar un paso adelante para conseguir la fecha que está buscando.

20

La versión independiente del idioma:

para conseguir el primer día determinado del mes, empezar con el primer día del mes: aaaa-mm-01. Use cualquier función disponible para dar un número correspondiente al día de la semana. Reste ese número del día que está buscando; por ejemplo, si el primer día del mes es el miércoles (2) y está buscando el viernes (4), reste 2 de 4, dejando 2. Si la respuesta es negativa, agregue 7. Finalmente agregue eso al primero de el mes; para mi ejemplo, el primer viernes sería el tercero.

Para obtener el último viernes del mes, encuentre el primer viernes del mes siguiente y reste 7 días.

0

Averigüe cuál es el primer y el último día del mes en cuestión (es decir, el 1 de mayo de 2009 es un viernes y el 31 de mayo de 2009 es domingo) Creo que la mayoría de las funciones de PHP usan lunes = 0, domingo = 6 , por lo tanto, viernes = 4, entonces usted sabe que el domingo (6) - viernes (4) = 2, luego 31-2 = 29, lo que significa que el último viernes de este mes es el día 29. Para el primer viernes, si el número es negativo, agregue 7, si el número es 0, el mes comienza el viernes.

8

strtotime() puede ayudar. p.ej.

<?php 
$tsFirst = strtotime('2009-04-00 next friday'); 
$tsLast = strtotime('2009-05-01 last friday'); 
echo date(DATE_RFC850, $tsFirst), " | ", date(DATE_RFC850, $tsLast);
impresiones
Friday, 03-Apr-09 00:00:00 CEST | Friday, 24-Apr-09 00:00:00 CEST

+0

que ya revisé, no es compatible con "el penúltimo" o similar, y es mucho más lento. – MartinodF

6

No hay necesidad de cálculos o bucles - esto es muy fácil de hacer con strtotime():

Encuentra el enésimo o última aparición de un día en particular de un particular, un mes:

///////////////////////////////////////////////////////////////// 
// Quick Code 
///////////////////////////////////////////////////////////////// 

// Convenience mapping. 
$Names = array(0=>"Sun", 1=>"Mon", 2=>"Tue", 3=>"Wed", 4=>"Thu", 5=>"Fri", 6=>"Sat"); 

// Specify what we want 
// In this example, the Second Monday of Next March 
$tsInMonth = strtotime('March'); 
$Day = 1; 
$Ord = 2; 

// The actual calculations 
$ThisMonthTS = strtotime(date("Y-m-01", $tsInMonth)); 
$NextMonthTS = strtotime(date("Y-m-01", strtotime("next month", $tsInMonth))); 
$DateOfInterest = (-1 == $Ord) 
    ? strtotime("last ".$Names[$Day], $NextMonthTS) 
    : strtotime($Names[$Day]." + ".($Ord-1)." weeks", $ThisMonthTS); 


///////////////////////////////////////////////////////////////// 
// Explanation 
///////////////////////////////////////////////////////////////// 

// Specify the month of which we are interested. 
// You can use any timestamp inside that month, I'm using strtotime for convenience. 
$tsInMonth = strtotime('March'); 

// The day of interest, ie: Friday. 
// It can be 0=Sunday through 6=Saturday (Like 'w' from date()). 
$Day = 5; 

// The occurrence of this day in which we are interested. 
// It can be 1, 2, 3, 4 for the first, second, third, and fourth occurrence of the day in question in the month in question. 
// You can also use -1 to fine the LAST occurrence. That will return the fifth occurrence if there is one, else the 4th. 
$Ord = 3; 

//////////////////////////////////////////////////////////////// 
// We now have all the specific values we need. 
// The example values above specify the 3rd friday of next march 
//////////////////////////////////////////////////////////////// 

// We need the day name that corresponds with our day number to pass to strtotime(). 
// This isn't really necessary = we could just specify the string in the first place, but for date calcs, you are more likely to have the day number than the string itself, so this is convenient. 
$Names = array(0=>"Sun", 1=>"Mon", 2=>"Tue", 3=>"Wed", 4=>"Thu", 5=>"Fri", 6=>"Sat"); 

// Calculate the timestamp at midnight of the first of the month in question. 
// Remember $tsInMonth is any date in that month. 
$ThisMonthTS = strtotime(date("Y-m-01", $tsInMonth)); 

// Calculate the timestamp at midnight of the first of the FOLLOWING month. 
// This will be used if we specify -1 for last occurrence. 
$NextMonthTS = strtotime(date("Y-m-01", strtotime("next month", $tsInMonth))); 

// Now we just format the values a bit and pass them to strtotime(). 
// To find the 1,2,3,4th occurrence, we work from the first of the month forward. 
// For the last (-1) occurence,work we work back from the first occurrence of the following month. 
$DateOfInterest = (-1 == $Ord) ? 
    strtotime("last ".$Names[$Day], $NextMonthTS) : // The last occurrence of the day in this month. Calculated as "last dayname" from the first of next month, which will be the last one in this month. 
    strtotime($Names[$Day]." + ".($Ord-1)." weeks", $ThisMonthTS); // From the first of this month, move to "next dayname" which will be the first occurrence, and then move ahead a week for as many additional occurrences as you need. 
+0

Muchas gracias – beardedlinuxgeek

+0

@beardedlinuxgeek - My Pleasure. – Eli

1
function get_date($month, $year, $week, $day) { 
    # $month, $year: current month to search in 
    # $week: 0=1st, 1=2nd, 2=3rd, 3=4th, -1=last 
    # $day: 0=mon, 1=tue, ..., 6=sun 

    $startday=1; $delta=0; 
    if ($week < 0) { 
     $startday = date('t', mktime(0, 0, 0, $month, 1, $year)); # 28..31 
     $delta=1; 
    } 
    $start = mktime(0, 0, 0, $month, $startday, $year); 
    $dstart = date('w', $start)-1; # last of the month falls on 0=mon,6=sun 
    $offset=$day-$dstart; if ($offset<$delta){$offset+=7;} 
    $newday=$startday+$offset+($week*7); 
    return mktime(0, 0, 0, $month, $newday, $year); 
} 

Esto funciona para mí, y con base en la versión independiente del idioma :-) Sólo una lástima, que tenía que hacer que el delta-cosa (por si el último día de el mes es el día de la semana deseado, no necesitamos restar 7)

5

Las funciones de tiempo integradas de PHP lo hacen simple.

http://php.net/manual/en/function.strtotime.php

// Get first Friday of next month. 
$timestamp = strtotime('first fri of next month'); 

// Get second to last Friday of the current month. 
$timestamp = strtotime('last fri of this month -7 days'); 

// Format a timestamp as a human-meaningful string. 
$formattedDate = date('F j, Y', strtotime('first wed of last month')); 

Tenga en cuenta que nosotros siempre queremos estar seguros de que hemos definido la zona horaria correcta para su uso con strtotime para que PHP tiene una comprensión de dónde la marca de tiempo para calcular en relación con lo que la zona horaria la máquina piensa que es en.

date_default_timezone_set('America/New_York'); 
$formattedDate = date('F j, Y', strtotime('first wed of last month +1 week')); 
4
echo date('Y-m-d',strtotime('last friday')); 
0

la misma puede realizarse con mucha elegancia utilizando la clase DateTime.

$time_zone = new DateTimeZone('Europe/Ljubljana'); 

$first_friday_of_this_month = new DateTime('first Friday of this month', $time_zone); 
$last_friday_of_this_month = new DateTime('last Friday of this month', $time_zone); 

echo $first_friday_of_this_month->format('Y-m-d'); # 2015-11-06 
echo $last_friday_of_this_month->format('Y-m-d'); # 2015-11-27 
0

Esto parece funcionar perfectamente cada vez; toma cualquier fecha provista y devuelve la fecha del último viernes del mes, incluso en el caso de 5 viernes en el mes.

function get_last_friday_of_month($inDate) { 
    $inDate = date('Y-m-24', strtotime($inDate)); 
    $last_friday = date('Y-m-d',strtotime($inDate.' next friday')); 
    $next_friday = date('Y-m-d',strtotime($inDate.' next friday')); 

    if(date('m', strtotime($last_friday)) === date('m', strtotime($next_friday))){ 
     $last_friday = $next_friday; 
    }else{ 
     // 
    } 
    return $last_friday; 
} 
0

A continuación encontrará la solución más rápida y la puede usar en cualquier condición. También podrías obtener una variedad de todos los días de la semana si lo retocas un poco.

function findDate($date, $week, $weekday){ 
    # $date is the date we are using to get the month and year which should be a datetime object 
    # $week can be: 0 for first, 1 for second, 2 for third, 3 for fourth and -1 for last 
    # $weekday can be: 1 for Monday, 2 for Tuesday, 3 for Wednesday, 4 for Thursday, 5 for Friday, 6 for Saturday and 7 for Sunday 

    $start = clone $date; 
    $finish = clone $date; 

    $start->modify('first day of this month'); 
    $finish->modify('last day of this month'); 
    $finish->modify('+1 day'); 

    $interval = DateInterval::createFromDateString('1 day'); 
    $period = new DatePeriod($start, $interval, $finish); 

    foreach($period AS $date){ 
     $result[$date->format('N')][] = $date; 
    } 

    if($week == -1) 
     return end($result[$weekday]); 
    else 
     return $result[$weekday][$week]; 
} 


$date = DateTime::createFromFormat('d/m/Y', '25/12/2016'); 

# find the third Wednesday in December 2016 
$result = findDate($date, 2, 3); 
echo $result->format('d/m/Y'); 

Espero que esto ayude.

Deseo saber si necesita más información.

Cuestiones relacionadas