https://redmine.ruby-lang.org/
https://redmine.ruby-lang.org/favicon.ico?1711330511
2015-09-30T08:55:17Z
Ruby Issue Tracking System
Ruby master - Feature #11558: Time related C APIs
https://redmine.ruby-lang.org/issues/11558?journal_id=54325
2015-09-30T08:55:17Z
akr (Akira Tanaka)
akr@fsij.org
<ul></ul><p>Yui NARUSE wrote:</p>
<blockquote>
<p>Time関連のC APIを追加して欲しいです。</p>
</blockquote>
<p>要望は理解できます。</p>
<blockquote>
<p>struct timespecとoffsetを取って、Timeを返してください。<br>
VALUE rb_time_timespec_new(const struct timespec *ts, int offset);<br>
趣旨としては、[秒, ナノ秒, offset]からTimeを作って欲しいと言うことです。<br>
(rb_time_num_new(Rational, offset)とかだと手間かかる上に遅い)</p>
</blockquote>
<p>いいんじゃないでしょうか。</p>
<blockquote>
<p>現在時刻をstruct timespecで欲しいです。<br>
void timespec_now(struct timespec *ts);</p>
</blockquote>
<p>Ruby の定義であることがわかる prefix が名前に必要だと思います。</p>
<blockquote>
<p>既存の非公開APIを公開してください。<br>
struct tm * localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, const char **zone);</p>
</blockquote>
<p>time_t を使うと 2038年問題を考慮しないといけないので、よくないと思います。<br>
struct tm を使うと (tm_year が int なので) 2**31年問題を考慮しないといけないので、よくないと思います。<br>
zone を char * で返すのはメモリ管理に責任を持てなくなるので、よくないと思います。</p>
<blockquote>
<p>time_t timegm_noleapsecond(struct tm *tm);</p>
</blockquote>
<p>time_t と struct tm は上記のようによくないと思います。</p>
<blockquote>
<p>void tm_add_offset(struct tm *tm, long diff);</p>
</blockquote>
<p>struct tm は上記のようによくないと思います。<br>
tm_year が overflow したらどうするんでしょうか。</p>
<p>まぁ、time_t と struct tm が癌なので、Ruby の公開API用の構造体を定義すれば解決できるとは思います。<br>
(あと zone は Ruby 内部で VALUE で扱うことに変えないといけないと思う。)</p>
Ruby master - Feature #11558: Time related C APIs
https://redmine.ruby-lang.org/issues/11558?journal_id=54326
2015-09-30T10:12:46Z
naruse (Yui NARUSE)
naruse@airemix.jp
<ul></ul><p>Akira Tanaka wrote:</p>
<blockquote>
<p>Yui NARUSE wrote:</p>
<blockquote>
<p>既存の非公開APIを公開してください。<br>
struct tm * localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, const char **zone);</p>
</blockquote>
<p>time_t を使うと 2038年問題を考慮しないといけないので、よくないと思います。<br>
struct tm を使うと (tm_year が int なので) 2**31年問題を考慮しないといけないので、よくないと思います。</p>
</blockquote>
<p>time_tは入力なので、このAPIが考える必要は必ずしもないのではありませんか。<br>
内部処理はyearはint64_tでやって、struct tmにつっこむときにエラーを返せばいいかな。</p>
<blockquote>
<p>zone を char * で返すのはメモリ管理に責任を持てなくなるので、よくないと思います。</p>
</blockquote>
<p>これは確かにNULLを渡すことしか考えていなかったので、zoneを削除したものにした方がよいですね。</p>
<blockquote>
<blockquote>
<p>time_t timegm_noleapsecond(struct tm *tm);</p>
</blockquote>
<p>time_t と struct tm は上記のようによくないと思います。</p>
</blockquote>
<p>こちらはtimet_t (32bit) が危ないですね。<br>
入力はstruct tmのままで、戻り値は64bitですかねぇ。</p>
<blockquote>
<blockquote>
<p>void tm_add_offset(struct tm *tm, long diff);</p>
</blockquote>
<p>struct tm は上記のようによくないと思います。<br>
tm_year が overflow したらどうするんでしょうか。</p>
</blockquote>
<p>tm_yearがint64_tでもギリギリ狙ったらあふれますよね。<br>
さておき、戻り値intにしてエラー返すのがよいかな。</p>
<blockquote>
<p>まぁ、time_t と struct tm が癌なので、Ruby の公開API用の構造体を定義すれば解決できるとは思います。</p>
</blockquote>
<p>VALUEにしないかぎり、入力を納められる出力のサイズ問題は解決不可能ではありませんか。<br>
VALUEにはしたくありませんが……。</p>
<p>そういえば、struct timespecもtv_sevはtime_tですね。</p>
Ruby master - Feature #11558: Time related C APIs
https://redmine.ruby-lang.org/issues/11558?journal_id=54327
2015-09-30T12:07:07Z
akr (Akira Tanaka)
akr@fsij.org
<ul></ul><p>Yui NARUSE wrote:</p>
<blockquote>
<blockquote>
<blockquote>
<p>struct tm * localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, const char **zone);</p>
</blockquote>
<p>time_t を使うと 2038年問題を考慮しないといけないので、よくないと思います。</p>
</blockquote>
</blockquote>
<blockquote>
<p>time_tは入力なので、このAPIが考える必要は必ずしもないのではありませんか。<br>
内部処理はyearはint64_tでやって、struct tmにつっこむときにエラーを返せばいいかな。</p>
</blockquote>
<p>アプリケーションに time_t の値が与えられるのであればそうでしょうが、<br>
アプリケーションが time_t の値を生成するのであれば、表現できなかったらどうするかというのは問題になるでしょう。<br>
それはアプリケーションの責任であり、Ruby の責任ではない、という趣旨なのだとは思いますが、<br>
実際のところアプリケーションが対処するのは難しいでしょうし、<br>
2038年問題が現実に問題になることはそれなりにあるのではないでしょうか。</p>
<blockquote>
<blockquote>
<blockquote>
<p>time_t timegm_noleapsecond(struct tm *tm);</p>
</blockquote>
<p>time_t と struct tm は上記のようによくないと思います。</p>
</blockquote>
<p>こちらはtimet_t (32bit) が危ないですね。<br>
入力はstruct tmのままで、戻り値は64bitですかねぇ。</p>
</blockquote>
<p>エラーをどう表現するのか、というのも問題ですね。<br>
-1 にすると 1969-12-31 23:59:59 UTC と区別がつかないんだよなぁ。</p>
<blockquote>
<blockquote>
<blockquote>
<p>void tm_add_offset(struct tm *tm, long diff);</p>
</blockquote>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p>tm_year が overflow したらどうするんでしょうか。</p>
</blockquote>
<p>tm_yearがint64_tでもギリギリ狙ったらあふれますよね。<br>
さておき、戻り値intにしてエラー返すのがよいかな。</p>
</blockquote>
<p>えぇ、void だとエラーを返せませんよね。</p>
<blockquote>
<p>VALUEにしないかぎり、入力を納められる出力のサイズ問題は解決不可能ではありませんか。<br>
VALUEにはしたくありませんが……。</p>
</blockquote>
<p>VALUE にするか、64bit 整数型にするか、あるいは time.c の wideint_t みたいなことをするか、<br>
というのが選択肢ですね。</p>
<p>VALUE にすると 32bit 環境で 1970年からの秒数が Bignum になるので遅く、<br>
64bit 整数型にすると値の範囲の制限は残るためちゃんとエラーを扱わなければならず、<br>
wideint_t みたいなのは話が大がかりなものになる、<br>
というのが主な得失でしょうか。</p>
<blockquote>
<p>そういえば、struct timespecもtv_sevはtime_tですね。</p>
</blockquote>
<p>えぇ、time_t というよりは struct timespec の代わりの型をつくったほうがいいでしょうね。<br>
struct timespec を受け付ける API 自体は、扱えないときに fallback する先があれば問題ないのですが。<br>
(あと現在時刻を struct timespec で返すのは問題ないと思います。)</p>
Ruby master - Feature #11558: Time related C APIs
https://redmine.ruby-lang.org/issues/11558?journal_id=54755
2015-11-08T06:44:19Z
naruse (Yui NARUSE)
naruse@airemix.jp
<ul></ul><p>とりあえず特に異論の無かった下記を入れようかと思います。</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index af6b75d..3fb1637 100644
</span><span class="gd">--- a/include/ruby/intern.h
</span><span class="gi">+++ b/include/ruby/intern.h
</span><span class="p">@@ -919,8 +919,10 @@</span> 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 */
<span class="gi">+void rb_timespec_now(struct timespec *);
</span> VALUE rb_time_new(time_t, long);
VALUE rb_time_nano_new(time_t, long);
<span class="gi">+VALUE rb_time_timespec_new(const struct timespec *, int);
</span> VALUE rb_time_num_new(VALUE, VALUE);
struct timeval rb_time_interval(VALUE num);
struct timeval rb_time_timeval(VALUE time);
<span class="gh">diff --git a/time.c b/time.c
index 11c76a5..da8cf25 100644
</span><span class="gd">--- a/time.c
</span><span class="gi">+++ b/time.c
</span><span class="p">@@ -1892,6 +1892,25 @@</span> timew2timespec_exact(wideval_t timew, struct timespec *ts)
return ts;
}
<span class="gi">+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
+}
+
</span> static VALUE
time_init_0(VALUE time)
{
<span class="p">@@ -1903,20 +1922,7 @@</span> time_init_0(VALUE time)
tobj->gmt = 0;
tobj->tm_got=0;
tobj->timew = WINT2FIXWV(0);
<span class="gd">-#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
</span><span class="gi">+ rb_timespec_now(&ts);
</span> tobj->timew = timespec2timew(&ts);
return time;
<span class="p">@@ -2306,6 +2312,23 @@</span> rb_time_nano_new(time_t sec, long nsec)
}
VALUE
<span class="gi">+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
</span> rb_time_num_new(VALUE timev, VALUE off)
{
VALUE time = time_new_timew(rb_cTime, rb_time_magnify(v2w(timev)));
</code></pre>
Ruby master - Feature #11558: Time related C APIs
https://redmine.ruby-lang.org/issues/11558?journal_id=54831
2015-11-12T03:40:07Z
naruse (Yui NARUSE)
naruse@airemix.jp
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Closed</i></li></ul>