class DateTime
DateTime
Подкласс Date, который позволяет легко работать с датой, часом, минутой, секундой и смещением.
Класс DateTime считается устаревшим. Используйте класс Time.
DateTime не учитывает високосные секунды и не отслеживает правила перехода на летнее время.
Объект DateTime создаётся с помощью DateTime::new, DateTime::jd, DateTime::ordinal, DateTime::commercial, DateTime::parse, DateTime::strptime, DateTime::now, Time#to_datetime и т. д.
require 'date'
DateTime.new(2001,2,3,4,5,6)
#=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>
DateTime.new(2001,2,3.5)
#=> #<DateTime: 2001-02-03T12:00:00+00:00 ...>
Необязательный аргумент — смещение — указывает разницу между местным временем и временем UTC. Например, Rational(3,24) означает, что время опережает UTC на 3 часа, а Rational(-5,24) — что оно отстаёт от UTC на 5 часов. Смещение должно находиться в диапазоне от -1 до +1, а его точность, как предполагается, составляет не более одной секунды. Значение по умолчанию — ноль (то есть UTC).
DateTime.new(2001,2,3,4,5,6,Rational(3,24))
#=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>
Смещение также можно указать в виде строки:
DateTime.new(2001,2,3,4,5,6,'+03:00')
#=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>
Необязательный аргумент — день календарной реформы (start) — обозначает номер юлианского дня, который должен находиться в диапазоне от 2298874 до 2426355 или быть отрицательной/положительной бесконечностью. Значение по умолчанию — Date::ITALY (2299161=1582-10-15).
У объекта DateTime есть различные методы. См. описание каждого из них.
d = DateTime.parse('3rd Feb 2001 04:05:06+03:30')
#=> #<DateTime: 2001-02-03T04:05:06+03:30 ...>
d.hour #=> 4
d.min #=> 5
d.sec #=> 6
d.offset #=> (7/48)
d.zone #=> "+03:30"
d += Rational('1.5')
#=> #<DateTime: 2001-02-04%16:05:06+03:30 ...>
d = d.new_offset('+09:00')
#=> #<DateTime: 2001-02-04%21:35:06+09:00 ...>
d.strftime('%I:%M:%S %p')
#=> "09:35:06 PM"
d > DateTime.new(1999)
#=> true
Когда следует использовать DateTime, а когда — Time?
Распространено ошибочное мнение, что Уильям Шекспир и Мигель де Сервантес умерли в один и тот же день — настолько распространённое, что ЮНЕСКО объявила 23 апреля Всемирным днём книги именно из-за этого факта. Однако Англия ещё не перешла на григорианскую календарную реформу (и сделала это лишь в 1752 году), поэтому на самом деле их смерти разделяют 10 дней. Поскольку класс Ruby Time реализует пролептический григорианский календарь и не учитывает календарную реформу, выразить это с помощью объектов Time невозможно. Здесь на помощь приходит DateTime:
shakespeare = DateTime.iso8601('1616-04-23', Date::ENGLAND)
#=> Tue, 23 Apr 1616 00:00:00 +0000
cervantes = DateTime.iso8601('1616-04-23', Date::ITALY)
#=> Sat, 23 Apr 1616 00:00:00 +0000
Уже видно, что что-то не так: дни недели различаются. Рассмотрим это подробнее:
cervantes == shakespeare #=> false (shakespeare - cervantes).to_i #=> 10
Это показывает, что на самом деле их смерти разделяют 10 дней (в действительности — 11, поскольку Сервантес умер на день раньше, но был похоронен 23-го числа). Узнать фактическую дату смерти Шекспира можно с помощью метода gregorian, преобразовав дату:
shakespeare.gregorian #=> Tue, 03 May 1616 00:00:00 +0000
Таким образом, можно утверждать, что все празднования, проходящие 23 апреля в Стратфорде-на-Эйвоне, на самом деле проводятся не в ту дату, поскольку сейчас Англия использует григорианский календарь. Это становится понятно при переходе через границу даты реформы:
# start off with the anniversary of Shakespeare's birth in 1751
shakespeare = DateTime.iso8601('1751-04-23', Date::ENGLAND)
#=> Tue, 23 Apr 1751 00:00:00 +0000
# add 366 days since 1752 is a leap year and April 23 is after February 29
shakespeare + 366
#=> Thu, 23 Apr 1752 00:00:00 +0000
# add another 365 days to take us to the anniversary in 1753
shakespeare + 366 + 365
#=> Fri, 04 May 1753 00:00:00 +0000
Как видите, если точно отслеживать количество солнечных лет, прошедших со дня рождения Шекспира, то правильной датой годовщины будет 4 мая, а не 23 апреля.
Так когда же в Ruby следует использовать DateTime, а когда — Time? Почти наверняка вам понадобится Time, поскольку ваше приложение, вероятно, работает с текущими датами и временем. Однако если вам нужно работать с датами и временем в историческом контексте, используйте DateTime, чтобы не повторять ошибок ЮНЕСКО. Если вам также нужно учитывать часовые пояса, удачи: просто имейте в виду, что, вероятно, вам придётся работать с местным солнечным временем, поскольку необходимость в стандартном времени, а впоследствии и в часовых поясах возникла лишь в XIX веке с появлением железных дорог.
Открытые методы класса
static VALUE
datetime_s__strptime(int argc, VALUE *argv, VALUE klass)
{
return date_s__strptime_internal(argc, argv, klass, "%FT%T%z");
} Разбирает заданное представление даты и времени с использованием заданного шаблона и возвращает хеш разобранных элементов. В отличие от strftime, _strptime не поддерживает указание флагов и ширины.
См. также strptime(3) и strftime.
static VALUE
datetime_s_civil(int argc, VALUE *argv, VALUE klass)
{
return datetime_initialize(argc, argv, d_lite_s_alloc_complex(klass));
} То же, что и DateTime.new.
static VALUE
datetime_s_commercial(int argc, VALUE *argv, VALUE klass)
{
VALUE vy, vw, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
int w, d, h, min, s, rof;
double sg;
rb_scan_args(argc, argv, "08", &vy, &vw, &vd, &vh, &vmin, &vs, &vof, &vsg);
y = INT2FIX(-4712);
w = 1;
d = 1;
h = min = s = 0;
fr2 = INT2FIX(0);
rof = 0;
sg = DEFAULT_SG;
switch (argc) {
case 8:
val2sg(vsg, sg);
case 7:
val2off(vof, rof);
case 6:
check_numeric(vs, "second");
num2int_with_frac(s, positive_inf);
case 5:
check_numeric(vmin, "minute");
num2int_with_frac(min, 5);
case 4:
check_numeric(vh, "hour");
num2int_with_frac(h, 4);
case 3:
check_numeric(vd, "cwday");
num2int_with_frac(d, 3);
case 2:
check_numeric(vw, "cweek");
w = NUM2INT(vw);
case 1:
check_numeric(vy, "year");
y = vy;
}
{
VALUE nth;
int ry, rw, rd, rh, rmin, rs, rjd, rjd2, ns;
if (!valid_commercial_p(y, w, d, sg,
&nth, &ry,
&rw, &rd, &rjd,
&ns))
rb_raise(eDateError, "invalid date");
if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
rb_raise(eDateError, "invalid date");
canon24oc();
rjd2 = jd_local_to_utc(rjd,
time_to_df(rh, rmin, rs),
rof);
ret = d_complex_new_internal(klass,
nth, rjd2,
0, INT2FIX(0),
rof, sg,
0, 0, 0,
rh, rmin, rs,
HAVE_JD | HAVE_TIME);
}
add_frac();
return ret;
} Создает объект DateTime, обозначающий заданную календарную дату в формате недели.
DateTime.commercial(2001) #=> #<DateTime: 2001-01-01T00:00:00+00:00 ...>
DateTime.commercial(2002) #=> #<DateTime: 2001-12-31T00:00:00+00:00 ...>
DateTime.commercial(2001,5,6,4,5,6,'+7')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
static VALUE
datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
str = rb_str_new2(JULIAN_EPOCH_DATETIME_HTTPDATE);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
{
int argc2 = 1;
VALUE argv2[2], hash;
argv2[0] = str;
argv2[1] = opt;
if (!NIL_P(opt)) argc2++;
hash = date_s__httpdate(argc2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
} Создает новый объект DateTime, разбирая строку в соответствии с одним из форматов RFC 2616.
DateTime.httpdate('Sat, 03 Feb 2001 04:05:06 GMT')
#=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>
Вызывает исключение ArgumentError, если длина строки превышает limit. Эту проверку можно отключить, передав limit: nil, однако учтите, что разбор может занять много времени.
static VALUE
datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
str = rb_str_new2(JULIAN_EPOCH_DATETIME);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
{
int argc2 = 1;
VALUE argv2[2], hash;
argv2[0] = str;
argv2[1] = opt;
if (!NIL_P(opt)) argc2++;
hash = date_s__iso8601(argc2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
} Создает новый объект DateTime, разбирая строку в соответствии с одним из распространенных форматов ISO 8601.
DateTime.iso8601('2001-02-03T04:05:06+07:00')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
DateTime.iso8601('20010203T040506+0700')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
DateTime.iso8601('2001-W05-6T04:05:06+07:00')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
Вызывает исключение ArgumentError, если длина строки превышает limit. Эту проверку можно отключить, передав limit: nil, однако учтите, что разбор может занять много времени.
static VALUE
datetime_s_jd(int argc, VALUE *argv, VALUE klass)
{
VALUE vjd, vh, vmin, vs, vof, vsg, jd, fr, fr2, ret;
int h, min, s, rof;
double sg;
rb_scan_args(argc, argv, "06", &vjd, &vh, &vmin, &vs, &vof, &vsg);
jd = INT2FIX(0);
h = min = s = 0;
fr2 = INT2FIX(0);
rof = 0;
sg = DEFAULT_SG;
switch (argc) {
case 6:
val2sg(vsg, sg);
case 5:
val2off(vof, rof);
case 4:
check_numeric(vs, "second");
num2int_with_frac(s, positive_inf);
case 3:
check_numeric(vmin, "minute");
num2int_with_frac(min, 3);
case 2:
check_numeric(vh, "hour");
num2int_with_frac(h, 2);
case 1:
check_numeric(vjd, "jd");
num2num_with_frac(jd, 1);
}
{
VALUE nth;
int rh, rmin, rs, rjd, rjd2;
if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
rb_raise(eDateError, "invalid date");
canon24oc();
decode_jd(jd, &nth, &rjd);
rjd2 = jd_local_to_utc(rjd,
time_to_df(rh, rmin, rs),
rof);
ret = d_complex_new_internal(klass,
nth, rjd2,
0, INT2FIX(0),
rof, sg,
0, 0, 0,
rh, rmin, rs,
HAVE_JD | HAVE_TIME);
}
add_frac();
return ret;
} Создает объект DateTime, обозначающий заданный хронологический номер юлианского дня.
DateTime.jd(2451944) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...>
DateTime.jd(2451945) #=> #<DateTime: 2001-02-04T00:00:00+00:00 ...>
DateTime.jd(Rational('0.5'))
#=> #<DateTime: -4712-01-01T12:00:00+00:00 ...>
static VALUE
datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
str = rb_str_new2(JULIAN_EPOCH_DATETIME);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
{
int argc2 = 1;
VALUE argv2[2], hash;
argv2[0] = str;
argv2[1] = opt;
if (!NIL_P(opt)) argc2++;
hash = date_s__jisx0301(argc2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
} Создает новый объект DateTime, разбирая строку в соответствии с одним из распространенных форматов JIS X 0301.
DateTime.jisx0301('H13.02.03T04:05:06+07:00')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
Если эра не указана, для устаревшего формата предполагается эра Хэйсэй.
DateTime.jisx0301('13.02.03T04:05:06+07:00')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
Вызывает исключение ArgumentError, если длина строки превышает limit. Эту проверку можно отключить, передав limit: nil, однако учтите, что разбор может занять много времени.
# File ext/json/lib/json/add/date_time.rb, line 10
def self.json_create(object)
args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
of_a, of_b = object['of'].split('/')
if of_b and of_b != '0'
args << Rational(of_a.to_i, of_b.to_i)
else
args << of_a
end
args << object['sg']
civil(*args)
end См. as_json.
static VALUE
datetime_s_civil(int argc, VALUE *argv, VALUE klass)
{
return datetime_initialize(argc, argv, d_lite_s_alloc_complex(klass));
} То же, что и DateTime.new.
static VALUE
datetime_s_now(int argc, VALUE *argv, VALUE klass)
{
VALUE vsg, nth, ret;
double sg;
#ifdef HAVE_CLOCK_GETTIME
struct timespec ts;
#else
struct timeval tv;
#endif
time_t sec;
struct tm tm;
long sf, of;
int y, ry, m, d, h, min, s;
rb_scan_args(argc, argv, "01", &vsg);
if (argc < 1)
sg = DEFAULT_SG;
else
sg = NUM2DBL(vsg);
#ifdef HAVE_CLOCK_GETTIME
if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
rb_sys_fail("clock_gettime");
sec = ts.tv_sec;
#else
if (gettimeofday(&tv, NULL) == -1)
rb_sys_fail("gettimeofday");
sec = tv.tv_sec;
#endif
tzset();
if (!localtime_r(&sec, &tm))
rb_sys_fail("localtime");
y = tm.tm_year + 1900;
m = tm.tm_mon + 1;
d = tm.tm_mday;
h = tm.tm_hour;
min = tm.tm_min;
s = tm.tm_sec;
if (s == 60)
s = 59;
#ifdef HAVE_STRUCT_TM_TM_GMTOFF
of = tm.tm_gmtoff;
#elif defined(HAVE_TIMEZONE)
#if defined(HAVE_ALTZONE) && !defined(_AIX)
of = (long)-((tm.tm_isdst > 0) ? altzone : timezone);
#else
of = (long)-timezone;
if (tm.tm_isdst) {
time_t sec2;
tm.tm_isdst = 0;
sec2 = mktime(&tm);
of += (long)difftime(sec2, sec);
}
#endif
#elif defined(HAVE_TIMEGM)
{
time_t sec2;
sec2 = timegm(&tm);
of = (long)difftime(sec2, sec);
}
#else
{
struct tm tm2;
time_t sec2;
if (!gmtime_r(&sec, &tm2))
rb_sys_fail("gmtime");
tm2.tm_isdst = tm.tm_isdst;
sec2 = mktime(&tm2);
of = (long)difftime(sec, sec2);
}
#endif
#ifdef HAVE_CLOCK_GETTIME
sf = ts.tv_nsec;
#else
sf = tv.tv_usec * 1000;
#endif
if (of < -DAY_IN_SECONDS || of > DAY_IN_SECONDS) {
of = 0;
rb_warning("invalid offset is ignored");
}
decode_year(INT2FIX(y), -1, &nth, &ry);
ret = d_complex_new_internal(klass,
nth, 0,
0, LONG2NUM(sf),
(int)of, GREGORIAN,
ry, m, d,
h, min, s,
HAVE_CIVIL | HAVE_TIME);
{
get_d1(ret);
set_sg(dat, sg);
}
return ret;
} Создает объект DateTime, обозначающий текущее время.
DateTime.now #=> #<DateTime: 2011-06-11T21:20:44+09:00 ...>
static VALUE
datetime_s_ordinal(int argc, VALUE *argv, VALUE klass)
{
VALUE vy, vd, vh, vmin, vs, vof, vsg, y, fr, fr2, ret;
int d, h, min, s, rof;
double sg;
rb_scan_args(argc, argv, "07", &vy, &vd, &vh, &vmin, &vs, &vof, &vsg);
y = INT2FIX(-4712);
d = 1;
h = min = s = 0;
fr2 = INT2FIX(0);
rof = 0;
sg = DEFAULT_SG;
switch (argc) {
case 7:
val2sg(vsg, sg);
case 6:
val2off(vof, rof);
case 5:
check_numeric(vs, "second");
num2int_with_frac(s, positive_inf);
case 4:
check_numeric(vmin, "minute");
num2int_with_frac(min, 4);
case 3:
check_numeric(vh, "hour");
num2int_with_frac(h, 3);
case 2:
check_numeric(vd, "yday");
num2int_with_frac(d, 2);
case 1:
check_numeric(vy, "year");
y = vy;
}
{
VALUE nth;
int ry, rd, rh, rmin, rs, rjd, rjd2, ns;
if (!valid_ordinal_p(y, d, sg,
&nth, &ry,
&rd, &rjd,
&ns))
rb_raise(eDateError, "invalid date");
if (!c_valid_time_p(h, min, s, &rh, &rmin, &rs))
rb_raise(eDateError, "invalid date");
canon24oc();
rjd2 = jd_local_to_utc(rjd,
time_to_df(rh, rmin, rs),
rof);
ret = d_complex_new_internal(klass,
nth, rjd2,
0, INT2FIX(0),
rof, sg,
0, 0, 0,
rh, rmin, rs,
HAVE_JD | HAVE_TIME);
}
add_frac();
return ret;
} Создает объект DateTime, обозначающий заданную порядковую дату.
DateTime.ordinal(2001,34) #=> #<DateTime: 2001-02-03T00:00:00+00:00 ...>
DateTime.ordinal(2001,34,4,5,6,'+7')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
DateTime.ordinal(2001,-332,-20,-55,-54,'+7')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
static VALUE
datetime_s_parse(int argc, VALUE *argv, VALUE klass)
{
VALUE str, comp, sg, opt;
argc = rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt);
switch (argc) {
case 0:
str = rb_str_new2(JULIAN_EPOCH_DATETIME);
case 1:
comp = Qtrue;
case 2:
sg = INT2FIX(DEFAULT_SG);
}
{
int argc2 = 2;
VALUE argv2[3], hash;
argv2[0] = str;
argv2[1] = comp;
argv2[2] = opt;
if (!NIL_P(opt)) argc2++;
hash = date_s__parse(argc2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
} Разбирает заданное представление даты и времени и создает объект DateTime.
Этот метод не является валидатором. Если входная строка не соответствует допустимым форматам в точности, результат может оказаться непонятным. По возможности вместо этого метода следует использовать DateTime.strptime.
Если второй необязательный аргумент равен true, а обнаруженный год находится в диапазоне от «00» до «99», он преобразуется в полный год.
DateTime.parse('2001-02-03T04:05:06+07:00')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
DateTime.parse('20010203T040506+0700')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
DateTime.parse('3rd Feb 2001 04:05:06 PM')
#=> #<DateTime: 2001-02-03T16:05:06+00:00 ...>
Вызывает исключение ArgumentError, если длина строки превышает limit. Эту проверку можно отключить, передав limit: nil, однако учтите, что разбор может занять много времени.
static VALUE
datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
str = rb_str_new2(JULIAN_EPOCH_DATETIME_RFC3339);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
{
int argc2 = 1;
VALUE argv2[2], hash;
argv2[0] = str;
argv2[1] = opt;
if (!NIL_P(opt)) argc2++;
hash = date_s__rfc2822(argc2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
} Создает новый объект DateTime, разбирая строку в соответствии с одним из распространенных форматов RFC 2822.
DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
Вызывает исключение ArgumentError, если длина строки превышает limit. Эту проверку можно отключить, передав limit: nil, однако учтите, что разбор может занять много времени.
static VALUE
datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
str = rb_str_new2(JULIAN_EPOCH_DATETIME);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
{
int argc2 = 1;
VALUE argv2[2], hash;
argv2[0] = str;
argv2[1] = opt;
if (!NIL_P(opt)) argc2++;
hash = date_s__rfc3339(argc2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
} Создает новый объект DateTime, разбирая строку в соответствии с одним из распространенных форматов RFC 3339.
DateTime.rfc3339('2001-02-03T04:05:06+07:00')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
Вызывает исключение ArgumentError, если длина строки превышает limit. Эту проверку можно отключить, передав limit: nil, однако учтите, что разбор может занять много времени.
static VALUE
datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
str = rb_str_new2(JULIAN_EPOCH_DATETIME_RFC3339);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
{
int argc2 = 1;
VALUE argv2[2], hash;
argv2[0] = str;
argv2[1] = opt;
if (!NIL_P(opt)) argc2++;
hash = date_s__rfc2822(argc2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
} Создает новый объект DateTime, разбирая строку в соответствии с одним из распространенных форматов RFC 2822.
DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
Вызывает исключение ArgumentError, если длина строки превышает limit. Эту проверку можно отключить, передав limit: nil, однако учтите, что разбор может занять много времени.
static VALUE
datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
{
VALUE str, fmt, sg;
rb_scan_args(argc, argv, "03", &str, &fmt, &sg);
switch (argc) {
case 0:
str = rb_str_new2(JULIAN_EPOCH_DATETIME);
case 1:
fmt = rb_str_new2("%FT%T%z");
case 2:
sg = INT2FIX(DEFAULT_SG);
}
{
VALUE argv2[2], hash;
argv2[0] = str;
argv2[1] = fmt;
hash = date_s__strptime(2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
} Разбирает заданное представление даты и времени с использованием заданного шаблона и создает объект DateTime. В отличие от strftime, strptime не поддерживает указание флагов и ширины.
DateTime.strptime('2001-02-03T04:05:06+07:00', '%Y-%m-%dT%H:%M:%S%z')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
DateTime.strptime('03-02-2001 04:05:06 PM', '%d-%m-%Y %I:%M:%S %p')
#=> #<DateTime: 2001-02-03T16:05:06+00:00 ...>
DateTime.strptime('2001-W05-6T04:05:06+07:00', '%G-W%V-%uT%H:%M:%S%z')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
DateTime.strptime('2001 04 6 04 05 06 +7', '%Y %U %w %H %M %S %z')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
DateTime.strptime('2001 05 6 04 05 06 +7', '%Y %W %u %H %M %S %z')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
DateTime.strptime('-1', '%s')
#=> #<DateTime: 1969-12-31T23:59:59+00:00 ...>
DateTime.strptime('-1000', '%Q')
#=> #<DateTime: 1969-12-31T23:59:59+00:00 ...>
DateTime.strptime('sat3feb014pm+7', '%a%d%b%y%H%p%z')
#=> #<DateTime: 2001-02-03T16:00:00+07:00 ...>
См. также strptime(3) и strftime.
static VALUE
datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
str = rb_str_new2(JULIAN_EPOCH_DATETIME);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
{
int argc2 = 1;
VALUE argv2[2], hash;
argv2[0] = str;
argv2[1] = opt;
if (!NIL_P(opt)) argc2++;
hash = date_s__xmlschema(argc2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
} Создает новый объект DateTime, разбирая строку в соответствии с одним из распространенных форматов XML Schema.
DateTime.xmlschema('2001-02-03T04:05:06+07:00')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
Вызывает исключение ArgumentError, если длина строки превышает limit. Эту проверку можно отключить, передав limit: nil, однако учтите, что разбор может занять много времени.
Открытые методы экземпляра
# File ext/json/lib/json/add/date_time.rb, line 39
def as_json(*)
{
JSON.create_id => self.class.name,
'y' => year,
'm' => month,
'd' => day,
'H' => hour,
'M' => min,
'S' => sec,
'of' => offset.to_s,
'sg' => start,
}
end Методы DateTime#as_json и DateTime.json_create можно использовать для сериализации и десериализации объекта DateTime; см. Marshal.
Метод DateTime#as_json сериализует self, возвращая хеш из двух элементов, представляющий self:
require 'json/add/datetime'
x = DateTime.now.as_json
# => {"json_class"=>"DateTime", "y"=>2023, "m"=>11, "d"=>21, "sg"=>2299161.0}
Метод JSON.create десериализует такой хеш и возвращает объект DateTime:
DateTime.json_create(x) # BUG? Raises Date::Error "invalid date"
static VALUE
dt_lite_deconstruct_keys(VALUE self, VALUE keys)
{
return deconstruct_keys(self, keys, /* is_datetime=true */ 1);
} Возвращает хеш пар имя/значение для сопоставления с образцом. Возможные ключи: :year, :month, :day, :wday, :yday, :hour, :min, :sec, :sec_fraction, :zone.
Возможные варианты использования:
dt = DateTime.new(2022, 10, 5, 13, 30)
if d in wday: 1..5, hour: 10..18 # uses deconstruct_keys underneath
puts "Working time"
end
#=> prints "Working time"
case dt
in year: ...2022
puts "too old"
in month: ..9
puts "quarter 1-3"
in wday: 1..5, month:
puts "working day in month #{month}"
end
#=> prints "working day in month 10"
Обратите внимание, что деструктуризацию с помощью сопоставления с образцом можно также сочетать с проверкой класса:
if d in DateTime(wday: 1..5, hour: 10..18, day: ..7) puts "Working time, first week of the month" end
static VALUE
d_lite_hour(VALUE self)
{
get_d1(self);
return INT2FIX(m_hour(dat));
} Возвращает час в диапазоне (0..23):
DateTime.new(2001, 2, 3, 4, 5, 6).hour # => 4
static VALUE
dt_lite_iso8601(int argc, VALUE *argv, VALUE self)
{
long n = 0;
rb_check_arity(argc, 0, 1);
if (argc >= 1)
n = NUM2LONG(argv[0]);
return rb_str_append(strftimev("%Y-%m-%d", self, set_tmx),
iso8601_timediv(self, n));
} Этот метод эквивалентен strftime(‘%FT%T%:z’). Необязательный аргумент n задает количество цифр для дробной части секунд.
DateTime.parse('2001-02-03T04:05:06.123456789+07:00').iso8601(9)
#=> "2001-02-03T04:05:06.123456789+07:00"
static VALUE
dt_lite_jisx0301(int argc, VALUE *argv, VALUE self)
{
long n = 0;
rb_check_arity(argc, 0, 1);
if (argc >= 1)
n = NUM2LONG(argv[0]);
return rb_str_append(d_lite_jisx0301(self),
iso8601_timediv(self, n));
} Возвращает строку в формате JIS X 0301. Необязательный аргумент n задает количество цифр для дробной части секунд.
DateTime.parse('2001-02-03T04:05:06.123456789+07:00').jisx0301(9)
#=> "H13.02.03T04:05:06.123456789+07:00"
static VALUE
d_lite_min(VALUE self)
{
get_d1(self);
return INT2FIX(m_min(dat));
} Возвращает минуту в диапазоне (0..59):
DateTime.new(2001, 2, 3, 4, 5, 6).min # => 5
static VALUE
d_lite_new_offset(int argc, VALUE *argv, VALUE self)
{
VALUE vof;
int rof;
rb_scan_args(argc, argv, "01", &vof);
rof = 0;
if (argc >= 1)
val2off(vof, rof);
return dup_obj_with_new_offset(self, rof);
} Создает копию self и сбрасывает ее смещение.
d = DateTime.new(2001,2,3,4,5,6,'-02:00')
#=> #<DateTime: 2001-02-03T04:05:06-02:00 ...>
d.new_offset('+09:00') #=> #<DateTime: 2001-02-03T15:05:06+09:00 ...>
static VALUE
d_lite_offset(VALUE self)
{
get_d1(self);
return m_of_in_day(dat);
} Возвращает смещение.
DateTime.parse('04pm+0730').offset #=> (5/16)
static VALUE
dt_lite_rfc3339(int argc, VALUE *argv, VALUE self)
{
return dt_lite_iso8601(argc, argv, self);
} Этот метод эквивалентен strftime(‘%FT%T%:z’). Необязательный аргумент n задает количество цифр для дробной части секунд.
DateTime.parse('2001-02-03T04:05:06.123456789+07:00').rfc3339(9)
#=> "2001-02-03T04:05:06.123456789+07:00"
static VALUE
d_lite_sec(VALUE self)
{
get_d1(self);
return INT2FIX(m_sec(dat));
} Возвращает секунду в диапазоне (0..59):
DateTime.new(2001, 2, 3, 4, 5, 6).sec # => 6
static VALUE
d_lite_sec_fraction(VALUE self)
{
get_d1(self);
return m_sf_in_sec(dat);
} Возвращает дробную часть секунды в диапазоне (Rational(0, 1)…Rational(1, 1)):
DateTime.new(2001, 2, 3, 4, 5, 6.5).sec_fraction # => (1/2)
static VALUE
dt_lite_strftime(int argc, VALUE *argv, VALUE self)
{
return date_strftime_internal(argc, argv, self,
"%Y-%m-%dT%H:%M:%S%:z", set_tmx);
} Возвращает строковое представление self, отформатированное в соответствии с заданным +format:
DateTime.now.strftime # => "2022-07-01T11:03:19-05:00"
Другие форматы см. в разделе Форматы дат и времени:
static VALUE
datetime_to_date(VALUE self)
{
get_d1a(self);
if (simple_dat_p(adat)) {
VALUE new = d_lite_s_alloc_simple(cDate);
{
get_d1b(new);
bdat->s = adat->s;
bdat->s.jd = m_local_jd(adat);
return new;
}
}
else {
VALUE new = d_lite_s_alloc_simple(cDate);
{
get_d1b(new);
copy_complex_to_simple(new, &bdat->s, &adat->c);
bdat->s.jd = m_local_jd(adat);
bdat->s.flags &= ~(HAVE_DF | HAVE_TIME | COMPLEX_DAT);
return new;
}
}
} Возвращает объект Date, обозначающий self.
static VALUE
datetime_to_datetime(VALUE self)
{
return self;
} Возвращает self.
# File ext/json/lib/json/add/date_time.rb, line 62 def to_json(*args) as_json.to_json(*args) end
Возвращает строку JSON, представляющую self:
require 'json/add/datetime' puts DateTime.now.to_json
Результат:
{"json_class":"DateTime","y":2023,"m":11,"d":21,"sg":2299161.0}
static VALUE
dt_lite_to_s(VALUE self)
{
return strftimev("%Y-%m-%dT%H:%M:%S%:z", self, set_tmx);
} Возвращает строку в формате ISO 8601. (Этот метод не использует расширенные представления.)
DateTime.new(2001,2,3,4,5,6,'-7').to_s
#=> "2001-02-03T04:05:06-07:00"
static VALUE
datetime_to_time(VALUE self)
{
get_d1(self);
if (m_julian_p(dat)) {
VALUE g = d_lite_gregorian(self);
get_d1a(g);
dat = adat;
self = g;
}
{
VALUE t;
t = rb_funcall(rb_cTime,
rb_intern("new"),
7,
m_real_year(dat),
INT2FIX(m_mon(dat)),
INT2FIX(m_mday(dat)),
INT2FIX(m_hour(dat)),
INT2FIX(m_min(dat)),
f_add(INT2FIX(m_sec(dat)),
m_sf_in_sec(dat)),
INT2FIX(m_of(dat)));
RB_GC_GUARD(self); /* may be the converted gregorian */
return t;
}
} Возвращает объект Time, обозначающий self.
Этот метод эквивалентен strftime(‘%FT%T%:z’). Необязательный аргумент n задает количество цифр для дробной части секунд.
DateTime.parse('2001-02-03T04:05:06.123456789+07:00').iso8601(9)
#=> "2001-02-03T04:05:06.123456789+07:00"
static VALUE
d_lite_zone(VALUE self)
{
get_d1(self);
return m_zone(dat);
} Возвращает часовой пояс.
DateTime.parse('04pm+0730').zone #=> "+07:30"
Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.