raku-type-dateish
role Dateish { ... }
Date와 DateTime은 모두 객체가 나타내는 연, 월, 일에 접근하는 기능과, 요일 계산 같은 관련 기능을 지원해요. 이 공통 기능을 한데 묶어준 역할이 Dateish예요.
Methods
method year
method year(Date:D: --> Int:D)
날짜의 연도를 돌려줘요.
say Date.new('2015-12-31').year; # OUTPUT: «2015»
say DateTime.new(date => Date.new('2015-12-24'), hour => 1).year; # OUTPUT: «2015»
method month
method month(Date:D: --> Int:D)
날짜의 월을 돌려줘요 (1..12).
say Date.new('2015-12-31').month; # OUTPUT: «12»
say DateTime.new(date => Date.new('2015-12-24'), hour => 1).month; # OUTPUT: «12»
method day
method day(Date:D: --> Int:D)
날짜의 일(day of the month)을 돌려줘요 (1..31).
say Date.new('2015-12-31').day; # OUTPUT: «31»
say DateTime.new(date => Date.new('2015-12-24'), hour => 1).day; # OUTPUT: «24»
method formatter
method formatter(Dateish:D:)
Str로 변환할 때 쓰는 포맷 함수를 돌려줘요. 객체를 만들 때 아무것도 주지 않았다면 기본 포맷터가 쓰여요. 그 경우 이 메서드는 Callable 타입 객체를 돌려줘요.
이 포맷 함수는 DateTime의 Str 메서드가 호출자(invocant)를 유일한 인자로 하여 호출해요.
my $dt = Date.new('2015-12-31'); # (no formatter specified)
say $dt.formatter.^name; # OUTPUT: «Callable»
my $us-format = sub ($self) { sprintf "%02d/%02d/%04d", .month, .day, .year given $self; };
$dt = Date.new('2015-12-31', formatter => $us-format);
say $dt.formatter.^name; # OUTPUT: «Sub»
say $dt; # OUTPUT: «12/31/2015»
method is-leap-year
method is-leap-year(Dateish:D: --> Bool:D)
Dateish 객체의 연도가 윤년이면 True를 돌려줘요.
say DateTime.new(:year<2016>).is-leap-year; # OUTPUT: «True»
say Date.new("1900-01-01").is-leap-year; # OUTPUT: «False»
method day-of-month
method day-of-month(Date:D: --> Int:D)
날짜의 일을 돌려줘요 (1..31). day 메서드와 동의어예요.
say Date.new('2015-12-31').day-of-month; # OUTPUT: «31»
say DateTime.new(date => Date.new('2015-12-24'), hour => 1).day-of-month; # OUTPUT: «24»
method day-of-week
method day-of-week(Date:D: --> Int:D)
요일을 돌려줘요. 1이 월요일, 2가 화요일, 그리고 일요일이 7이에요.
say Date.new('2015-12-31').day-of-week; # OUTPUT: «4»
say DateTime.new(date => Date.new('2015-12-24'), hour => 1).day-of-week; # OUTPUT: «4»
method day-of-year
method day-of-year(Date:D: --> Int:D)
그 해의 몇 번째 날인지를 돌려줘요 (1..366).
say Date.new('2015-12-31').day-of-year; # OUTPUT: «365»
say DateTime.new(date => Date.new('2015-03-24'), hour => 1).day-of-year; # OUTPUT: «83»
method days-in-year
method days-in-year(Dateish:D: --> Int:D)
Dateish 객체가 나타내는 해의 총 일수를 돌려줘요.
say Date.new("2016-01-02").days-in-year; # OUTPUT: «366»
say DateTime.new(:year<2100>, :month<2>).days-in-year; # OUTPUT: «365»
Rakudo 컴파일러 2022.12 릴리스부터 사용할 수 있어요.
method days-in-month
method days-in-month(Dateish:D: --> Int:D)
Dateish 객체가 나타내는 달의 총 일수를 돌려줘요.
say Date.new("2016-01-02").days-in-month; # OUTPUT: «31»
say DateTime.new(:year<10000>, :month<2>).days-in-month; # OUTPUT: «29»
method week
method week()
연도와 주(week) 번호 두 정수의 목록을 돌려줘요. 연초나 연말에는 주가 실제로 다른 해에 속할 수 있기 때문이에요.
my ($year, $week) = Date.new("2014-12-31").week;
say $year; # OUTPUT: «2015»
say $week; # OUTPUT: «1»
say Date.new('2015-01-31').week; # OUTPUT: «(2015 5)»
method week-number
method week-number(Date:D: --> Int:D)
호출자가 지정한 날짜의 주 번호 (1..53)를 돌려줘요. ISO는 그 해의 첫 주를 1월 4일을 포함하는 주로 정의해요. 그래서 1월 초 날짜는 종종 지난 해의 마지막 주에 속하고, 마찬가지로 12월의 마지막 며칠은 다음 해의 첫 주에 들어가기도 해요.
say Date.new("2014-12-31").week-number; # OUTPUT: «1» (first week of 2015)
say Date.new("2016-01-02").week-number; # OUTPUT: «53» (last week of 2015)
method week-year
method week-year(Date:D: --> Int:D)
호출자가 지정한 날짜의 **주 연도(week year)**를 돌려줘요. 보통 주 연도는 Date.year와 같아요. 다만 1월 초 날짜가 지난 해의 마지막 주에 속하고, 12월의 마지막 며칠이 다음 해의 첫 주에 들어가는 경우가 있으니 주의하세요.
say Date.new("2015-11-15").week-year; # OUTPUT: «2015»
say Date.new("2014-12-31").week-year; # OUTPUT: «2015» (date belongs to the first week of 2015)
say Date.new("2016-01-02").week-year; # OUTPUT: «2015» (date belongs to the last week of 2015)
method weekday-of-month
method weekday-of-month(Date:D: --> Int:D)
그 달 동안 특정 요일이 몇 번째로 나타났는지 (1..5)를 돌려줘요. 그날 자체도 세어요.
say Date.new("2003-06-09").weekday-of-month; # OUTPUT: «2» (second Monday of the month)
method yyyy-mm-dd
method yyyy-mm-dd(str $sep = "-" --> Str:D)
날짜를 YYYY-MM-DD 형식(ISO 8601)으로 돌려줘요. 기본값이 -인 선택적 위치 인자 $sep은 날짜의 각 부분 사이에 들어가는 한 글자 구분자예요.
say Date.new("2015-11-15").yyyy-mm-dd; # OUTPUT: «2015-11-15»
say DateTime.new(1470853583).yyyy-mm-dd; # OUTPUT: «2016-08-10»
say Date.today.yyyy-mm-dd("/"); # OUTPUT: «2020/03/14»
method mm-dd-yyyy
method mm-dd-yyyy(str $sep = "-" --> Str:D)
날짜를 MM-DD-YYYY 형식(그레고리력, 월-일-연, MDY)으로 돌려줘요. 선택적 위치 인자 $sep은 날짜의 각 부분 사이에 들어가는 한 글자 구분자예요.
say Date.new("2015-11-15").mm-dd-yyyy; # OUTPUT: «11-15-2015»
say DateTime.new(1470853583).mm-dd-yyyy; # OUTPUT: «08-10-2016»
say Date.today.mm-dd-yyyy("/"); # OUTPUT: «03/14/2020»
method dd-mm-yyyy
method dd-mm-yyyy(str $sep = "-" --> Str:D)
날짜를 DD-MM-YYYY 형식(그레고리력, 일-월-연, DMY)으로 돌려줘요. 선택적 위치 인자 $sep은 날짜의 각 부분 사이에 들어가는 한 글자 구분자예요.
say Date.new("2015-11-15").dd-mm-yyyy; # OUTPUT: «15-11-2015»
say DateTime.new(1470853583).dd-mm-yyyy; # OUTPUT: «10-08-2016»
say Date.today.dd-mm-yyyy("/"); # OUTPUT: «14/03/2020»
method daycount
method daycount(Dateish:D: --> Int:D)
기준일(epoch)인 1858년 11월 17일부터 호출자가 나타내는 날까지의 일수를 돌려줘요. 이 메서드가 돌려주는 daycount는 **수정 줄리언 일(Modified Julian Day, MJD)**의 정수 부분이에요. MJD는 천문학자·측지학자·과학자 등이 일상적으로 쓰는 값이죠. MJD 관례는 연대 계산을 단순화하도록 설계됐어요. MJD의 소수 부분은 사용 중인 DateTime 객체의 시·분·초를 24시간의 상당 분수로 변환한 값이에요. 이 두 값을 더한 것이 그 순간의 MJD예요.
say Date.new('1995-09-27').daycount; # OUTPUT: «49987»
method IO
method IO(Dateish:D: --> IO::Path:D)
Dateish 객체를 문자열화한 값을 나타내는 IO::Path 객체를 돌려줘요.
Date.today.IO.say; # OUTPUT: «"2016-10-03".IO»
DateTime.now.IO.say; # OUTPUT: «"2016-10-03T11:14:47.977994-04:00".IO»
이식성 참고: 일부 운영체제(예: Windows)는 파일 이름에 콜론(:)을 허용하지 않는데, DateTime 객체에서 만든 IO::Path에는 콜론이 들어갈 수 있어요.
method earlier
multi method earlier(Dateish:D: *%unit)
multi method earlier(Dateish:D: @pairs)
지금 객체를 기준으로 하되, 과거 방향으로 날짜 델타를 적용한 객체를 돌려줘요. 주어진 단위가 second/seconds가 아니면 값은 Int로 변환돼요. 사용법은 .later를 보면 돼요. 보통 이 역할을 구현하는 클래스, 즉 Date나 DateTime을 통해 쓰게 돼요.
my $d = Date.new('2015-02-27');
say $d.earlier(month => 5).earlier(:2days); # OUTPUT: «2014-09-25»
my $d = DateTime.new(date => Date.new('2015-02-27'));
say $d.earlier(month => 1).earlier(:2days); # OUTPUT: «2015-01-25T00:00:00Z»
결과 시간의 초가 60인데 실제로 그 시간에 윤초가 없다면, 초는 59로 설정돼요.
say DateTime.new('2008-12-31T23:59:60Z').earlier: :1day;
# OUTPUT: «2008-12-30T23:59:59Z»
음수 오프셋도 허용되지만, 그런 용도에는 later가 더 관용적이에요.
한 번에 여러 단위를 써야 한다면, 그것들을 Pair들의 List로 묶어서 두 번째 형식을 쓰면 돼요.
say Date.new('2021-03-31').earlier( ( year => 3, month => 2, day => 8 ) ); # OUTPUT: «2018-01-23»
이 기능은 Rakudo 컴파일러 2021.02 릴리스에서 도입됐어요.
method later
multi method later(DateTime:D: *%unit)
지금 객체(이 역할을 섞은 어떤 클래스든)를 기준으로 시간 델타를 적용한 객체를 돌려줘요. 시간 델타는 인자 이름이 단위인 이름 붙은 인자로 넘길 수 있어요.
주어진 단위가 second/seconds가 아니면 값은 Int로 변환돼요.
허용되는 단위는 second, seconds, minute, minutes, hour, hours, day, days, week, weeks, month, months, year, years예요. 복수형은 later와 earlier 메서드에서만 쓸 수 있다는 점을 기억해 두세요.
:2nd 형태의 콜론페어를 쓰면 델타를 간결하고 자명하게 지정할 수 있어요.
say DateTime.new('2015-12-24T12:23:00Z').later(:2years);
# OUTPUT: «2017-12-24T12:23:00Z»
여러 종류의 시간 단위를 더하는 것은 교환 법칙이 성립하지 않기 때문에, 단위는 하나만 넘길 수 있어요 (그래서 첫 번째 multi가 쓰여요).
my $d = DateTime.new(date => Date.new('2015-02-27'));
say $d.later(month => 1).later(:2days); # OUTPUT: «2015-03-29T00:00:00Z»
say $d.later(days => 2).later(:1month); # OUTPUT: «2015-04-01T00:00:00Z»
say $d.later(days => 2).later(:month); # same, as +True === 1
(Rakudo 컴파일러 2021.02 릴리스부터) 여러 단위를 동시에 넘길 수도 있는데, 그 경우 두 번째 형식을 쓰기 위해 그것들을 List로 묶어야 해요.
say DateTime.new(date => Date.new('2015-02-27')).later( (:1month, :2days) )
# OUTPUT: «2015-03-29T00:00:00Z»
결과 시간의 초가 60인데 실제로 그 시간에 윤초가 없다면, 초는 59로 설정돼요.
say DateTime.new('2008-12-31T23:59:60Z').later: :1day;
# OUTPUT: «2009-01-01T23:59:59Z»
음수 오프셋도 허용되지만, 그런 용도에는 earlier가 더 관용적이에요.
Date 타입의 객체도 똑같이 동작해요.
my $d = Date.new('2015-02-27');
say $d.later(month => 1).later(:2days); # OUTPUT: «2015-03-29»
say $d.later(days => 2).later(:1month); # OUTPUT: «2015-04-01»
say $d.later(days => 2).later(:month); # same, as +True === 1