class DateTime - Documentation for Ruby 3.3

# class DateTime

## `DateTime`¶ ↑

A subclass of `Date` that easily handles date, hour, minute, second, and offset.

`DateTime` class is considered deprecated. Use `Time` class.

`DateTime` does not consider any leap seconds, does not track any summer time rules.

A `DateTime` object is created with `DateTime::new`, `DateTime::jd`, `DateTime::ordinal`, `DateTime::commercial`, `DateTime::parse`, `DateTime::strptime`, `DateTime::now`, `Time#to_datetime`, etc.

    require 'date'

    DateTime.new(2001,2,3,4,5,6)
                        #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>

The last element of day, hour, minute, or second can be a fractional number. The fractional number’s precision is assumed at most nanosecond.

    DateTime.new(2001,2,3.5)
                        #=> #<DateTime: 2001-02-03T12:00:00+00:00 ...>

An optional argument, the offset, indicates the difference between the local time and UTC. For example, `Rational(3,24)` represents ahead of 3 hours of UTC, `Rational(-5,24)` represents behind of 5 hours of UTC. The offset should be -1 to +1, and its precision is assumed at most second. The default value is zero (equals to UTC).

    DateTime.new(2001,2,3,4,5,6,Rational(3,24))
                        #=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>

The offset also accepts string form:

    DateTime.new(2001,2,3,4,5,6,'+03:00')
                        #=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>

An optional argument, the day of calendar reform (`start`), denotes a Julian day number, which should be 2298874 to 2426355 or negative/positive infinity. The default value is `Date::ITALY` (2299161=1582-10-15).

A `DateTime` object has various methods. See each reference.

    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

### When should you use `DateTime` and when should you use `Time`?¶ ↑

It’s a common misconception that William Shakespeare and Miguel de Cervantes died on the same day in history - so much so that UNESCO named April 23 as World Book Day because of this fact. However, because England hadn’t yet adopted the Gregorian Calendar Reform (and wouldn’t until 1752) their deaths are actually 10 days apart. Since Ruby’s `Time` class implements a proleptic Gregorian calendar and has no concept of calendar reform there’s no way to express this with `Time` objects. This is where `DateTime` steps in:

    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

Already you can see something is weird - the days of the week are different. Taking this further:

    cervantes == shakespeare
     #=> false
    (shakespeare - cervantes).to_i
     #=> 10

This shows that in fact they died 10 days apart (in reality 11 days since Cervantes died a day earlier but was buried on the 23rd). We can see the actual date of Shakespeare’s death by using the `gregorian` method to convert it:

    shakespeare.gregorian
     #=> Tue, 03 May 1616 00:00:00 +0000

So there’s an argument that all the celebrations that take place on the 23rd April in Stratford-upon-Avon are actually the wrong date since England is now using the Gregorian calendar. You can see why when we transition across the reform date boundary:

    # 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

As you can see, if we’re accurately tracking the number of solar years since Shakespeare’s birthday then the correct anniversary date would be the 4th May and not the 23rd April.

So when should you use `DateTime` in Ruby and when should you use `Time`? Almost certainly you’ll want to use `Time` since your app is probably dealing with current dates and times. However, if you need to deal with dates and times in a historical context you’ll want to use `DateTime` to avoid making the same mistakes as UNESCO. If you also have to deal with timezones then best of luck - just bear in mind that you’ll probably be dealing with local solar times, since it wasn’t until the 19th century that the introduction of the railways necessitated the need for Standard Time and eventually timezones.

### Public Class Methods

_strptime(string[, format='%FT%T%z']) → hash click to toggle source

Parses the given representation of date and time with the given template, and returns a hash of parsed elements. _strptime does not support specification of flags and width unlike strftime.

See also strptime(3) and `strftime`.

    static VALUE
    datetime_s__strptime(int argc, VALUE *argv, VALUE klass)
    {
        return date_s__strptime_internal(argc, argv, klass, "%FT%T%z");
    }

civil(*args) click to toggle source

Same as `DateTime.new`.

    static VALUE
    datetime_s_civil(int argc, VALUE *argv, VALUE klass)
    {
        return datetime_initialize(argc, argv, d_lite_s_alloc_complex(klass));
    }

commercial([cwyear=-4712[, cweek=1[, cwday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]]) → datetime click to toggle source

Creates a `DateTime` object denoting the given week date.

    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_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;
    }

httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=Date::ITALY]) → datetime click to toggle source

Creates a new `DateTime` object by parsing from a string according to some RFC 2616 format.

    DateTime.httpdate('Sat, 03 Feb 2001 04:05:06 GMT')
                              #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>

Raise an `ArgumentError` when the string length is longer than limit. You can stop this check by passing `limit: nil`, but note that it may take a long time to parse.

    static VALUE
    datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
    {
        VALUE str, sg, opt;

        rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
        if (!NIL_P(opt)) argc--;

        switch (argc) {
          case 0:
            str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT");
          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);
        }
    }

iso8601(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) → datetime click to toggle source

Creates a new `DateTime` object by parsing from a string according to some typical ISO 8601 formats.

    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 ...>

Raise an `ArgumentError` when the string length is longer than limit. You can stop this check by passing `limit: nil`, but note that it may take a long time to parse.

    static VALUE
    datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
    {
        VALUE str, sg, opt;

        rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
        if (!NIL_P(opt)) argc--;

        switch (argc) {
          case 0:
            str = rb_str_new2("-4712-01-01T00:00:00+00:00");
          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);
        }
    }

jd([jd=0[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]) → datetime click to toggle source

Creates a `DateTime` object denoting the given chronological Julian day number.

    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_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;
    }

jisx0301(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) → datetime click to toggle source

Creates a new `DateTime` object by parsing from a string according to some typical JIS X 0301 formats.

    DateTime.jisx0301('H13.02.03T04:05:06+07:00')
                              #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>

For no-era year, legacy format, Heisei is assumed.

    DateTime.jisx0301('13.02.03T04:05:06+07:00')
                              #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>

Raise an `ArgumentError` when the string length is longer than limit. You can stop this check by passing `limit: nil`, but note that it may take a long time to parse.

    static VALUE
    datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
    {
        VALUE str, sg, opt;

        rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
        if (!NIL_P(opt)) argc--;

        switch (argc) {
          case 0:
            str = rb_str_new2("-4712-01-01T00:00:00+00:00");
          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);
        }
    }

json_create(object) click to toggle source

See `as_json`.

    # 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

new(*args) click to toggle source

Same as `DateTime.new`.

    static VALUE
    datetime_s_civil(int argc, VALUE *argv, VALUE klass)
    {
        return datetime_initialize(argc, argv, d_lite_s_alloc_complex(klass));
    }

now([start=Date::ITALY]) → datetime click to toggle source

Creates a `DateTime` object denoting the present time.

    DateTime.now              #=> #<DateTime: 2011-06-11T21:20:44+09:00 ...>

    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;
    }

ordinal([year=-4712[, yday=1[, hour=0[, minute=0[, second=0[, offset=0[, start=Date::ITALY]]]]]]]) → datetime click to toggle source

Creates a `DateTime` object denoting the given ordinal date.

    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_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;
    }

parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]], limit: 128) → datetime click to toggle source

Parses the given representation of date and time, and creates a `DateTime` object.

This method does not function as a validator. If the input string does not match valid formats strictly, you may get a cryptic result. Should consider to use `DateTime.strptime` instead of this method as possible.

If the optional second argument is true and the detected year is in the range “00” to “99”, makes it full.

    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 ...>

Raise an `ArgumentError` when the string length is longer than limit. You can stop this check by passing `limit: nil`, but note that it may take a long time to parse.

    static VALUE
    datetime_s_parse(int argc, VALUE *argv, VALUE klass)
    {
        VALUE str, comp, sg, opt;

        rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt);
        if (!NIL_P(opt)) argc--;

        switch (argc) {
          case 0:
            str = rb_str_new2("-4712-01-01T00:00:00+00:00");
          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);
        }
    }

rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) → datetime click to toggle source
rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) → datetime

Creates a new `DateTime` object by parsing from a string according to some typical RFC 2822 formats.

    DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700')
                             #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>

Raise an `ArgumentError` when the string length is longer than limit. You can stop this check by passing `limit: nil`, but note that it may take a long time to parse.

    static VALUE
    datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
    {
        VALUE str, sg, opt;

        rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
        if (!NIL_P(opt)) argc--;

        switch (argc) {
          case 0:
            str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000");
          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);
        }
    }

rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) → datetime click to toggle source

Creates a new `DateTime` object by parsing from a string according to some typical RFC 3339 formats.

    DateTime.rfc3339('2001-02-03T04:05:06+07:00')
                              #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>

Raise an `ArgumentError` when the string length is longer than limit. You can stop this check by passing `limit: nil`, but note that it may take a long time to parse.

    static VALUE
    datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
    {
        VALUE str, sg, opt;

        rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
        if (!NIL_P(opt)) argc--;

        switch (argc) {
          case 0:
            str = rb_str_new2("-4712-01-01T00:00:00+00:00");
          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);
        }
    }

rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) → datetime click to toggle source
rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) → datetime

Creates a new `DateTime` object by parsing from a string according to some typical RFC 2822 formats.

    DateTime.rfc2822('Sat, 3 Feb 2001 04:05:06 +0700')
                             #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>

Raise an `ArgumentError` when the string length is longer than limit. You can stop this check by passing `limit: nil`, but note that it may take a long time to parse.

    static VALUE
    datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
    {
        VALUE str, sg, opt;

        rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
        if (!NIL_P(opt)) argc--;

        switch (argc) {
          case 0:
            str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000");
          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);
        }
    }

strptime([string='-4712-01-01T00:00:00+00:00'[, format='%FT%T%z'[ ,start=Date::ITALY]]]) → datetime click to toggle source

Parses the given representation of date and time with the given template, and creates a `DateTime` object. strptime does not support specification of flags and width unlike strftime.

    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 ...>

See also strptime(3) and `strftime`.

    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("-4712-01-01T00:00:00+00:00");
          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);
        }
    }

xmlschema(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) → datetime click to toggle source

Creates a new `DateTime` object by parsing from a string according to some typical XML Schema formats.

    DateTime.xmlschema('2001-02-03T04:05:06+07:00')
                              #=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>

Raise an `ArgumentError` when the string length is longer than limit. You can stop this check by passing `limit: nil`, but note that it may take a long time to parse.

    static VALUE
    datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
    {
        VALUE str, sg, opt;

        rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
        if (!NIL_P(opt)) argc--;

        switch (argc) {
          case 0:
            str = rb_str_new2("-4712-01-01T00:00:00+00:00");
          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);
        }
    }

### Public Instance Methods

as_json(*) click to toggle source

Methods `DateTime#as_json` and `DateTime.json_create` may be used to serialize and deserialize a DateTime object; see `Marshal`.

Method `DateTime#as_json` serializes `self`, returning a 2-element hash representing `self`:

    require 'json/add/datetime'
    x = DateTime.now.as_json
    # => {"json_class"=>"DateTime", "y"=>2023, "m"=>11, "d"=>21, "sg"=>2299161.0}

Method `JSON.create` deserializes such a hash, returning a DateTime object:

    DateTime.json_create(x) # BUG? Raises Date::Error "invalid date"

    # 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

deconstruct_keys(array_of_names_or_nil) → hash click to toggle source

Returns a hash of the name/value pairs, to use in pattern matching. Possible keys are: `:year`, `:month`, `:day`, `:wday`, `:yday`, `:hour`, `:min`, `:sec`, `:sec_fraction`, `:zone`.

Possible usages:

    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"

Note that deconstruction by pattern can also be combined with class check:

    if d in DateTime(wday: 1..5, hour: 10..18, day: ..7)
      puts "Working time, first week of the month"
    end

    static VALUE
    dt_lite_deconstruct_keys(VALUE self, VALUE keys)
    {
        return deconstruct_keys(self, keys, /* is_datetime=true */ 1);
    }

hour → integer click to toggle source

Returns the hour in range (0..23):

    DateTime.new(2001, 2, 3, 4, 5, 6).hour # => 4

    static VALUE
    d_lite_hour(VALUE self)
    {
        get_d1(self);
        return INT2FIX(m_hour(dat));
    }

iso8601([n=0]) → string click to toggle source

This method is equivalent to strftime(‘%FT%T%:z’). The optional argument `n` is the number of digits for fractional seconds.

    DateTime.parse('2001-02-03T04:05:06.123456789+07:00').iso8601(9)
                              #=> "2001-02-03T04:05:06.123456789+07:00"

    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));
    }

Also aliased as: xmlschema
jisx0301([n=0]) → string click to toggle source

Returns a string in a JIS X 0301 format. The optional argument `n` is the number of digits for fractional seconds.

    DateTime.parse('2001-02-03T04:05:06.123456789+07:00').jisx0301(9)
                              #=> "H13.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));
    }

min → integer click to toggle source

Returns the minute in range (0..59):

    DateTime.new(2001, 2, 3, 4, 5, 6).min # => 5

    static VALUE
    d_lite_min(VALUE self)
    {
        get_d1(self);
        return INT2FIX(m_min(dat));
    }

Also aliased as: minute
minute
Alias for: min
new_offset([offset=0]) → date click to toggle source

Duplicates self and resets its offset.

    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_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);
    }

offset → rational click to toggle source

Returns the offset.

    DateTime.parse('04pm+0730').offset        #=> (5/16)

    static VALUE
    d_lite_offset(VALUE self)
    {
        get_d1(self);
        return m_of_in_day(dat);
    }

rfc3339([n=0]) → string click to toggle source

This method is equivalent to strftime(‘%FT%T%:z’). The optional argument `n` is the number of digits for fractional seconds.

    DateTime.parse('2001-02-03T04:05:06.123456789+07:00').rfc3339(9)
                              #=> "2001-02-03T04:05:06.123456789+07:00"

    static VALUE
    dt_lite_rfc3339(int argc, VALUE *argv, VALUE self)
    {
        return dt_lite_iso8601(argc, argv, self);
    }

sec → integer click to toggle source

Returns the second in range (0..59):

    DateTime.new(2001, 2, 3, 4, 5, 6).sec # => 6

    static VALUE
    d_lite_sec(VALUE self)
    {
        get_d1(self);
        return INT2FIX(m_sec(dat));
    }

Also aliased as: second
sec_fraction → rational click to toggle source

Returns the fractional part of the second in range (Rational(0, 1)…Rational(1, 1)):

    DateTime.new(2001, 2, 3, 4, 5, 6.5).sec_fraction # => (1/2)

    static VALUE
    d_lite_sec_fraction(VALUE self)
    {
        get_d1(self);
        return m_sf_in_sec(dat);
    }

Also aliased as: second_fraction
second
Alias for: sec
second_fraction
Alias for: sec_fraction
strftime(format = '%FT%T%:z') → string click to toggle source

Returns a string representation of `self`, formatted according the given +format:

    DateTime.now.strftime # => "2022-07-01T11:03:19-05:00"

For other formats, see Formats for Dates and Times:

    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);
    }

to_date → date click to toggle source

Returns a `Date` object which denotes self.

    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;
            }
        }
    }

to_datetime → self click to toggle source

Returns self.

    static VALUE
    datetime_to_datetime(VALUE self)
    {
        return self;
    }

to_json(*args) click to toggle source

Returns a `JSON` string representing `self`:

    require 'json/add/datetime'
    puts DateTime.now.to_json

Output:

    {"json_class":"DateTime","y":2023,"m":11,"d":21,"sg":2299161.0}

    # File ext/json/lib/json/add/date_time.rb, line 62
    def to_json(*args)
      as_json.to_json(*args)
    end

to_s → string click to toggle source

Returns a string in an ISO 8601 format. (This method doesn’t use the expanded representations.)

    DateTime.new(2001,2,3,4,5,6,'-7').to_s
                             #=> "2001-02-03T04:05:06-07:00"

    static VALUE
    dt_lite_to_s(VALUE self)
    {
        return strftimev("%Y-%m-%dT%H:%M:%S%:z", self, set_tmx);
    }

to_time → time click to toggle source

Returns a `Time` object which denotes self.

    static VALUE
    datetime_to_time(VALUE self)
    {
        get_d1(self);

        if (m_julian_p(dat)) {
            self = d_lite_gregorian(self);
            get_d1a(self);
            dat = adat;
        }

        {
            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)));
            return t;
        }
    }

xmlschema([n=0]) → string

This method is equivalent to strftime(‘%FT%T%:z’). The optional argument `n` is the number of digits for fractional seconds.

    DateTime.parse('2001-02-03T04:05:06.123456789+07:00').iso8601(9)
                              #=> "2001-02-03T04:05:06.123456789+07:00"

Alias for: iso8601
zone → string click to toggle source

Returns the timezone.

    DateTime.parse('04pm+0730').zone          #=> "+07:30"

    static VALUE
    d_lite_zone(VALUE self)
    {
        get_d1(self);
        return m_zone(dat);
    }