raku-type-dateish

role Dateish { ... }

DateDateTime은 모두 객체가 나타내는 연, 월, 일에 접근하는 기능과, 요일 계산 같은 관련 기능을 지원해요. 이 공통 기능을 한데 묶어준 역할이 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 타입 객체를 돌려줘요.

이 포맷 함수는 DateTimeStr 메서드가 호출자(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를 보면 돼요. 보통 이 역할을 구현하는 클래스, 즉 DateDateTime을 통해 쓰게 돼요.

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예요. 복수형은 laterearlier 메서드에서만 쓸 수 있다는 점을 기억해 두세요.

: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