Issue #11558 has been updated by Yui NARUSE.


とりあえず特に異論の無かった下記を入れようかと思います。

```diff
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index af6b75d..3fb1637 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -919,8 +919,10 @@ VALUE rb_mutex_unlock(VALUE mutex);
 VALUE rb_mutex_sleep(VALUE self, VALUE timeout);
 VALUE rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg);
 /* time.c */
+void rb_timespec_now(struct timespec *);
 VALUE rb_time_new(time_t, long);
 VALUE rb_time_nano_new(time_t, long);
+VALUE rb_time_timespec_new(const struct timespec *, int);
 VALUE rb_time_num_new(VALUE, VALUE);
 struct timeval rb_time_interval(VALUE num);
 struct timeval rb_time_timeval(VALUE time);
diff --git a/time.c b/time.c
index 11c76a5..da8cf25 100644
--- a/time.c
+++ b/time.c
@@ -1892,6 +1892,25 @@ timew2timespec_exact(wideval_t timew, struct timespec *ts)
     return ts;
 }
 
+void
+rb_timespec_now(struct timespec *ts)
+{
+#ifdef HAVE_CLOCK_GETTIME
+    if (clock_gettime(CLOCK_REALTIME, ts) == -1) {
+	rb_sys_fail("clock_gettime");
+    }
+#else
+    {
+	struct timeval tv;
+	if (gettimeofday(&tv, 0) < 0) {
+	    rb_sys_fail("gettimeofday");
+	}
+	ts->tv_sec = tv.tv_sec;
+	ts->tv_nsec = tv.tv_usec * 1000;
+    }
+#endif
+}
+
 static VALUE
 time_init_0(VALUE time)
 {
@@ -1903,20 +1922,7 @@ time_init_0(VALUE time)
     tobj->gmt = 0;
     tobj->tm_got=0;
     tobj->timew = WINT2FIXWV(0);
-#ifdef HAVE_CLOCK_GETTIME
-    if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
-	rb_sys_fail("clock_gettime");
-    }
-#else
-    {
-        struct timeval tv;
-        if (gettimeofday(&tv, 0) < 0) {
-            rb_sys_fail("gettimeofday");
-        }
-        ts.tv_sec = tv.tv_sec;
-        ts.tv_nsec = tv.tv_usec * 1000;
-    }
-#endif
+    rb_timespec_now(&ts);
     tobj->timew = timespec2timew(&ts);
 
     return time;
@@ -2306,6 +2312,23 @@ rb_time_nano_new(time_t sec, long nsec)
 }
 
 VALUE
+rb_time_timespec_new(const struct timespec *ts, int offset)
+{
+    VALUE time = time_new_timew(rb_cTime, nsec2timew(ts->tv_sec, ts->tv_nsec));
+    if (offset) {
+	struct time_object *tobj;
+	if (offset < -86400 || 86400 < offset)
+	    rb_raise(rb_eArgError, "utc_offset out of range");
+	GetTimeval(time, tobj);
+	tobj->tm_got = 0;
+	tobj->gmt = 2;
+	tobj->vtm.utc_offset = INT2FIX(offset);
+	tobj->vtm.zone = NULL;
+    }
+    return time;
+}
+
+VALUE
 rb_time_num_new(VALUE timev, VALUE off)
 {
     VALUE time = time_new_timew(rb_cTime, rb_time_magnify(v2w(timev)));
```

----------------------------------------
Feature #11558: Time related C APIs
https://bugs.ruby-lang.org/issues/11558#change-54755

* Author: Yui NARUSE
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
Time関連のC APIを追加して欲しいです。
具体的には以下のようなものが欲しいです。

struct timespecとoffsetを取って、Timeを返してください。
VALUE rb_time_timespec_new(const struct timespec *ts, int offset);
趣旨としては、[秒, ナノ秒, offset]からTimeを作って欲しいと言うことです。
(rb_time_num_new(Rational, offset)とかだと手間かかる上に遅い)

現在時刻をstruct timespecで欲しいです。
void timespec_now(struct timespec *ts);


既存の非公開APIを公開してください。
struct tm * localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, const char **zone);
time_t timegm_noleapsecond(struct tm *tm);
void tm_add_offset(struct tm *tm, long diff);


https://github.com/nurse/strptime/blob/v0.1.1/ext/strptime/ruby_time.c



-- 
https://bugs.ruby-lang.org/