Issue #11558 has been updated by Akira Tanaka.


Yui NARUSE wrote:

> > > struct tm * localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, const char **zone);
> > 
> > time_t を使うと 2038年問題を考慮しないといけないので、よくないと思います。

> time_tは入力なので、このAPIが考える必要は必ずしもないのではありませんか。
> 内部処理はyearはint64_tでやって、struct tmにつっこむときにエラーを返せばいいかな。

アプリケーションに time_t の値が与えられるのであればそうでしょうが、
アプリケーションが time_t の値を生成するのであれば、表現できなかったらどうするかというのは問題になるでしょう。
それはアプリケーションの責任であり、Ruby の責任ではない、という趣旨なのだとは思いますが、
実際のところアプリケーションが対処するのは難しいでしょうし、
2038年問題が現実に問題になることはそれなりにあるのではないでしょうか。

> > > time_t timegm_noleapsecond(struct tm *tm);
> > 
> > time_t と struct tm は上記のようによくないと思います。
> 
> こちらはtimet_t (32bit) が危ないですね。
> 入力はstruct tmのままで、戻り値は64bitですかねぇ。

エラーをどう表現するのか、というのも問題ですね。
-1 にすると 1969-12-31 23:59:59 UTC と区別がつかないんだよなぁ。

> > > void tm_add_offset(struct tm *tm, long diff);

> > tm_year が overflow したらどうするんでしょうか。
> 
> tm_yearがint64_tでもギリギリ狙ったらあふれますよね。
> さておき、戻り値intにしてエラー返すのがよいかな。

えぇ、void だとエラーを返せませんよね。

> VALUEにしないかぎり、入力を納められる出力のサイズ問題は解決不可能ではありませんか。
> VALUEにはしたくありませんが……。

VALUE にするか、64bit 整数型にするか、あるいは time.c の wideint_t みたいなことをするか、
というのが選択肢ですね。

VALUE にすると 32bit 環境で 1970年からの秒数が Bignum になるので遅く、
64bit 整数型にすると値の範囲の制限は残るためちゃんとエラーを扱わなければならず、
wideint_t みたいなのは話が大がかりなものになる、
というのが主な得失でしょうか。

> そういえば、struct timespecもtv_sevはtime_tですね。

えぇ、time_t というよりは struct timespec の代わりの型をつくったほうがいいでしょうね。
struct timespec を受け付ける API 自体は、扱えないときに fallback する先があれば問題ないのですが。
(あと現在時刻を struct timespec で返すのは問題ないと思います。)


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

* 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/