PHP2010/02/03 19:27
먼저 토, 일요일을 제외한 국경일 및 명절 등을 정의합니다.
$holiday = array(
    '2010-01-01',
    '2010-02-15',
    '2010-03-01',
    '2010-05-05',
    '2010-05-21',
    '2010-09-21',
    '2010-09-22',
    '2010-09-23',
);


2010년 2월 26일부터 2일 휴가를 받았다고 가정하죠.
토, 일요일과 국경일 및 명절 등의 휴일을 제외하면 언제까지 휴가일까요?

2010년 2월 26일 금요일 - 1일
2010년 2월 27일 토요일 - 토요일이니 건너뛰고
2010년 2월 28일 일요일 - 역시 일요일이니 건너뛰고
2010년 3월 1일 월요일 - 국경일이군요.
2010년 3월 2일 화요일 - 2일. 이날까지군요.


이것을 프로그램으로 작성해볼까요?

1. 2010-02-26을 timestamp값을 바꿉니다.
$timestamp = strtotime('2010-02-26');

2. 이제 이 값을 이용해 요일값을 구합니다.
list($d,$w) = explode(' ',date('Y-m-d w',$timestamp));
"년-월-일 요일"값을 " "(공백) 기준으로 자르고, 각각 $d와 $w에 대입하는 코드입니다.
요일값은 0:일, 1:월, 2:화, 3:수, 4:목, 5:금, 6:토요일입니다.

3. 요일값($w)를 이용해 토요일이나 일요일인지 검사합니다.
if ( $w%6==0 ) echo '토, 일요일';
0을 6으로 나누면 나머지는 0, 6을 6으로 나누면 나머지는 0.
즉 0과 6인 경우만 조건이 참이 됩니다.

4. $holiday에 포함된 날짜인지 확인합니다.
if ( in_array($d,$holiday) ) echo '공휴일';

5. 3과 4에 속하는 경우 휴가 기간을 늘려줘야겠죠?
if ( $w%6==0 || in_array($d,$holiday) ) $추가++;
$추가 = 0; 미리 정의한 상태로 가정하지요.

6. 날짜를 하루 추가해줍니다.
$timestamp+= 86400;
60초 * 60분 * 24시간 = 86400 하루입니다.

7. 위 2번 과정을 반복합니다. 단 여기에 조건이 있어야겠죠?


이런 과정을 거친 정리된 코드입니다.

function holiday_check($date,$count)
{
    $timestamp = strtotime($date);
    $step = $plus = 0;
    while ( $step < $count )
    {
        list($d,$w) = explode(' ',date('Y-m-d w',$timestamp));
        $timestamp+= 86400;
        $step++;
        if ( $w%6==0 || in_array($d,$GLOBALS['holiday']) ) {
            $plus++; $step--;
        }
    }
    echo $d.' 추가:'.$plus.'일';
}
holiday_check('2010-02-26',2); // 2010-03-02 추가:3일

어때요? 참 쉽죠?
저작자 표시 비영리 변경 금지
Posted by BiHon

댓글을 달아 주세요

MySQL2010/02/03 18:09
2010-01-01 00:00:00부터 2010-02-03 23:59:59 사이의 임의의 날짜를 생성해볼까요?

먼저 알아야 할 것은 날짜 및 랜덤 관련 함수입니다.

UNIX_TIMESTAMP() 함수를 이용해 Timestamp를 구할 수 있죠?
아래의 예를 보세요.

SELECT UNIX_TIMESTAMP('2010-01-01 00:00:00');
UNIX_TIMESTAMP('2010-01-01 00:00:00')
1262271600

SELECT UNIX_TIMESTAMP('2010-02-04 00:00:00'); // 1초 더함. 이유는 아래
UNIX_TIMESTAMP('2010-02-04 00:00:00')
1265209200
= UNIX_TIMESTAMP('2010-02-03 23:59:59')+1

저 수치 사이의 값을 구하면 되겠죠?
이때 필요한 것이 RAND() 함수입니다.
이 함수로 0 이상, 1 미만의 부동 소수점 값을 구할 수있습니다. (0 ≤ n < 1) 이유!

SELECT RAND();
RAND()
0.298790559450901

정수 형태로 하려면 FLOOR() 함수를 사용해주면 됩니다.
예를 들어 1 이상 10 미만의 정수를 반환받고자 한다면 아래처럼 하면 됩니다.

SELECT FLOOR(1+RAND()*(10-1));
FLOOR(1+RAND()*(10-1))
3


지금까지의 함수를 통해 두 값 사이의 임의의 수(Timestamp)를 생성할 수 있겠죠?
그렇게 생성된 Timestamp 값을 FROM_UNIXTIME() 함수를 이용해 '년-월-일 시:분:초' 형태로 구할 수 있습니다.
최종적으로 아래 명령으로 구할 수 있습니다.

SELECT FROM_UNIXTIME(FLOOR(unix_timestamp('2010-01-01 00:00:00')+(RAND()*(unix_timestamp('2010-02-04 00:00:00')-unix_timestamp('2010-01-01 00:00:00')))));
FROM_UNIXTIME(FLOOR(unix_timestamp('2010-01-01 00:00:00')+(RAND()*(unix_timestamp('2010-02-04 00:00:00')-unix_timestamp('2010-01-01 00:00:00')))))
2010-01-21 23:37:01

Timestamp값을 그대로 넣으려면 FROM_UNIXTIME() 함수가 필요없겠죠?
년-월-일 또는 시간 등 필요한 문장으로 입력하려면 DATE_FORMAT() 함수를 사용하면 됩니다.
저작자 표시 비영리 변경 금지

'MySQL' 카테고리의 다른 글

지정한 두 기간 사이의 날짜 랜덤 생성  (0) 2010/02/03
Posted by BiHon

댓글을 달아 주세요

PHP2010/02/03 00:05
예를 위한 배열을 생성합니다.
$data = array(
'version'=>'1.0',
'code'=>array('test1','test2','test3','test4'),
'url'=>array(
    'type1'=>array('bihon.com','dreamphp.com'),
    'type2'=>array('phpschool.com','tistory.com'),
    'type3'=>array(),
    ),
'etc'=>'hahaha',
);
편의상 ,를 넣어줬어요.


값을 보기 좋게 늘어놓으면 다음과 같습니다. print_r() 이용.
Array
(
    [version] => 1.0
    [code] => Array
        (
            [0] => test1
            [1] => test2
            [2] => test3
            [3] => test4
        )
    [url] => Array
        (
            [type1] => Array
                (
                    [0] => bihon.com
                    [1] => dreamphp.com
                )
            [type2] => Array
                (
                    [0] => phpschool.com
                    [1] => tistory.com
                )
            [type3] => Array
                (
                )
        )
    [etc] => hahaha
)


배열의 크기를 구해볼까요?
echo count($data); // "4" 출력. version, code, url, etc


하위 포함해 전체의 크기를 구해볼까요?
echo count($data,COUNT_RECURSIVE); // count($data,1) "15" 출력
이 재귀 카운트는 4.2.0부터 사용할 수 있습니다.


키 값 빼고 순수한 값만 구해볼까요?
function array_size($array,$opt=0)
{
    $cnt = 0;
    foreach ( $array as $key => $value )
    {
        if ( is_array($value) ) { if ( $opt ) $cnt++; $cnt+= array_size($value,$opt); }
        else $cnt++;
    }
    return $cnt;
}
echo array_size($data); // "10" 출력


옵션에 1을 주면 count($data,COUNT_RECURSIVE)와 같은 결과를 얻을 수 있습니다.
echo array_size($data,1); // "15" 출력


배열의 크기 구하는 예제였습니다. ^^);
저작자 표시 비영리 변경 금지
Posted by BiHon

댓글을 달아 주세요

PHP2010/02/01 00:04
GNU Multiple Precision 함수를 이용하면 조합 가능한 수를 쉽게 구할 수 있습니다.

예를 들어 로또 번호 1부터 45까지의 번호에서 6개를 선택했을 때 나올 수 있는 조합 가능한 수는?

nCk = 45C6 = 45 Combination 6 이죠.

수학적인 설명은 건너뛰고 코드만 바로 올립니다.

$n = 45;
$k = 6;
$combination = gmp_strval(gmp_div_q(gmp_fact($n),gmp_mul(gmp_fact($k),gmp_fact($n-$k))));
echo $combination; // "8145060" 출력

           45!          45!     45*44*43*42*41*40   5864443200
45C6 = ----------- = ------- = ----------------- = ---------- = 8,145,060
       6!·(45-6)!    6!·39!      6*5*4*3*2*1          720

참고 : 팩토리얼(Factorial)
저작자 표시 비영리 변경 금지
Posted by BiHon

댓글을 달아 주세요

PHP2010/01/30 19:46
봄(Spring) 여름(Summer) 가을(Autumn) 겨울(Winter) 계절 구하기

대충 봄은 3월, 4월, 5월.
여름은 6월, 7월, 8월.
가을은 9월, 10월, 11월.
겨울은 12월, 1월, 2월로 계절을 나누고 있습니다.


각 달이 어느 계절에 속했는지 구하는 방법을 알아볼까요?

지정한 달을 12로 나눈 나머지를 구합니다. 12가 0이 되었죠?
 1월 %12 =  1
 2월 %12 =  2
 3월 %12 =  3
 4월 %12 =  4
 5월 %12 =  5
 6월 %12 =  6
 7월 %12 =  7
 8월 %12 =  8
 9월 %12 =  9
10월 %12 = 10
11월 %12 = 11
12월 %12 =  0

이제 나머지값을 3으로 나누고 소수 이하는 버립니다.
 0 / 3 = 0.000000 = 0
 1 / 3 = 0.333333 = 0
 2 / 3 = 0.666667 = 0
 3 / 3 = 1.000000 = 1
 4 / 3 = 1.333333 = 1
 5 / 3 = 1.666667 = 1
 6 / 3 = 2.000000 = 2
 7 / 3 = 2.333333 = 2
 8 / 3 = 2.666667 = 2
 9 / 3 = 3.000000 = 3
10 / 3 = 3.333333 = 3
11 / 3 = 3.666667 = 3

0부터 3까지의 값으로 정리되는군요. 이 값이 곧 계절값입니다.
0은 겨울
1은 봄
2는 여름
3은 가을

PHP 코드로 볼까요?
$month = 3;
$season = array('겨울','봄','여름','가을');
$where = (int)$month%12/3; // 1
echo $season[$where]; // "봄" 출력

계절 구하는 부분을 응용 차원에서 한 줄로 해볼까요?
$월 = 7;
$계절 = reset(array_slice(array('겨울','봄','여름','가을'),(int)$월%12/3));
echo $계절; // "여름" 출력

복잡해 보이나요? 설명 추가합니다.
array_slice()는 substr() 함수와 비슷합니다.
시작위치와 크기를 지정해 그 값을 가져올 수 있지요.
echo substr('BiHon & M2',0,5); // "BiHon" 출력

$계절 = array('겨울','봄','여름','가을');
$예1 = array_slice($계절,0,1); // 겨울
$예2 = array_slice($계절,2,1); // 여름
$예3 = array_slice($계절,2,2); // 여름, 가을
$예4 = array_slice($계절,-1); // 가을
$예5 = array_slice($계절,1,-1); // 봄, 여름

예를 보면 알 수 있겠죠? ^^);
월 값을 가공 0~3까지의 값을 구해 그 위치부터의 배열을 구합니다.
이때 배열 형태라 처음 값을 reset()을 이용해 꺼내줍니다.
reset() = http://php.net/manual/kr/function.reset.php

어때요? 간단하죠?


그러면 date() 함수를 이용해 현 시점의 계절을 알아볼까요?
echo reset(array_slice(array('겨울','봄','여름','가을'),(int)date('n')%12/3)); // "겨울" 출력

문자열 함수를 이용. 효율적인 면에서 제일 빠릅니다.
echo substr('WinterSpringSummerAutumn',(int)(date('n')%12/3)*6,6); // "Winter" 출력
저작자 표시 비영리 변경 금지
Posted by BiHon

댓글을 달아 주세요