/*
 *  call-seq:
 *     Time.at(time) => time
 *     Time.at(seconds_with_frac) => time
 *     Time.at(seconds, microseconds_with_frac) => time
 *  
 *  Creates a new time object with the value given by <i>time</i>,
 *  the given number of <i>seconds_with_frac</i>, or
 *  <i>seconds</i> and <i>microseconds_with_frac</i> from the Epoch.
 *  <i>seconds_with_frac</i> and <i>microseconds_with_frac</i>
 *  can be Integer, Float, Rational, or other Numeric.
 *  non-portable feature allows the offset to be negative on some systems.
 *     
 *     Time.at(0)            #=> 1969-12-31 18:00:00 -0600
 *     Time.at(Time.at(0))   #=> 1969-12-31 18:00:00 -0600
 *     Time.at(946702800)    #=> 1999-12-31 23:00:00 -0600
 *     Time.at(-284061600)   #=> 1960-12-31 00:00:00 -0600
 *     Time.at(946684800.2).usec #=> 200000
 *     Time.at(946684800, 123456.789).nsec #=> 123456789
 */

static VALUE
time_s_at(int argc, VALUE *argv, VALUE klass)
{
    struct timespec ts;
    VALUE time, t;

    if (rb_scan_args(argc, argv, "11", &time, &t) == 2) {
        ts.tv_sec = NUM2LONG(time);
        ts.tv_nsec = NUM2LONG(rb_funcall(t, id_mul, 1, INT2FIX(1000)));
    }
    else {
        ts = rb_time_timespec(time);
    }
    t = time_new_internal(klass, ts.tv_sec, ts.tv_nsec);
    if (TYPE(time) == T_DATA && RDATA(time)->dfree == time_free) {
        struct time_object *tobj, *tobj2;

        GetTimeval(time, tobj);
        GetTimeval(t, tobj2);
        tobj2->gmt = tobj->gmt;
    }
    return t;
}