Issue #9794 has been updated by Akira Tanaka.


tadayoshi funaba wrote:
> 言語の問題もあるんだろうけど、俺が英語に堪能でも Felipe Contreras に俺の考えを解らせるのは無理じゃないかという気がする。

私も "%s %z" がなんでそんなにいけないのか理解していません。

> 誤解のないよう少し補足しておくと、strcut tm で %s や %z を表現できない、という直接的な問題でもない。
> C の時刻関数群はオブジェクト指向では書かれてないけど、データや関数の集合によってどんなモノを表現しているのか
> 考えないと理解できない。C の時刻関数には、まず、地方時 (あるいは局所時) と世界時の区別しかなく、
> 基本的に地方時は与えられるもので自分では選べない。選べないという事は、strptime に与えて仮に形式的に受けつけたとしても
> 仕様に従えば、mktime (自明の地方時) や gmtime (世界時) ではそれを使う事ができないという事になる。
> それに、%z に対応するメンバーがあっても、普通は %s に対応するものがない、
> だから %s は年月日などにデコードされるが、
> これも自明な地方時か世界時しか選択肢がない。時差を持っていても矛盾が生じてしまう。
> これは https://bugs.ruby-lang.org/issues/7445#note-12 ですでに書いた。

Ruby の strptime は struct tm じゃなくて DateTime や Time のオブジェクトを生成し、
DateTime や Time のオブジェクトは自分がどんなモノなのかを自分自身で把握しているため、
"%s %z" についてはこのへんの問題は避けられるように思っています。

%s と %z に対応する値を s と z として、
Time.at(s).getlocal(z) とするのがそれほどおかしいことだとは思っていません。

> そもそも %s は可搬性に乏しい (存在しない実装もあるだろうし、閏秒の挿入の課題がある)。
> 環境によっては、ruby の Time と DateTime でも結果に相違が出る。そういうものです。

閏秒については同意します。
その点があるので私もおすすめはしません。

%s が存在しない実装、ということについては、どういう意味かわかりません。
今の Ruby 本体は C の strptime() も strftime() も使っていません。
勘違いしていなければ、ext/date も使っていないように思います。
そのため環境に依存する部分はないように思います。

なお、strftime() を使わなくなったのは以下の変更からです。

```
Thu Aug 21 00:20:05 2008  Shugo Maeda  <shugo / ruby-lang.org>

        * strftime.c: new file.

        * common.mk (COMMONOBJS): added strftime.$(OBJEXT).

        * time.c (time_strftime): do not use strftime(3).  supported
          %L(millisecond) and %N(nanosecond).

        * test/ruby/test_time.rb: added tests for %L and %N.
```

この変更の理由は struct tm が小数点以下の秒を表現できないので %L や %N をサポートできないから、
というものですが、このときに %s の値も直接渡すようにもなっています。

> 俺は strptime が完璧だとは思ってないし、偏見の塊かもしれないと思っている。
> 田中さんなんかはそういう割切り方に自信があって、なおかつダメなものは諦めるしないと思っているのかもしれないけど、
> 俺の場合、少なくとも strptime については次善の策を用意しておいた。
> _strptime は lib/time.rb に使って貰う為に用意したわけではない。
> strptime でダメでも _strptime を叩いてどうにかなるかもしれない。
> 今回の件は明かに何とかなるでしょ。

ふなばさんはわかっているような気もするのですが、lib/time.rb の strptime と私との関係について、
知らない人も多いような気がするのでいちおう書いておきますと、
lib/time.rb に strptime を足したのはまつもとさんです。
その時点で意見や判断を求められたことはなく、関わっていません。

```
Fri Mar  4 08:09:12 2005  Yukihiro Matsumoto  <matz / ruby-lang.org>

        * lib/time.rb (Time::strptime): add new function.  inspired by
          [ruby-talk:132815].

        * lib/parsedate.rb (ParseDate::strptime): ditto.
```

その後で私も実装をいじっていたりもするので、まったく関係ないとまではいえないのですが。



----------------------------------------
Bug #9794: DateTime.strptime() doesn't work correctly for '%s %z'
https://bugs.ruby-lang.org/issues/9794#change-46473

* Author: Felipe Contreras
* Status: Rejected
* Priority: Low
* Assignee: tadayoshi funaba
* Category: ext
* Target version: 
* ruby -v: 2.1.1p76
* Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN
----------------------------------------
Time.strptime() works correctly:

    Time.strptime('0 +0100', '%s %z').strftime('%s %z')
    => "0 +0100"

But DateTime.strptime() doesn't:

    DateTime.strptime('0 +0100', '%s %z').strftime('%s %z')
    => "0 +0000"

In Rubinious it does work correctly:

    DateTime.strptime('0 +0100', '%s %z').strftime('%s %z')
    => "0 +0100"

This make the RubySL date space fail:

    DateTime#strptime parses seconds and timezone correctly FAILED
    Expected "1970-01-01T00:00:00+00:00"
     to equal "1970-01-01T01:00:00+01:00"

In addition, both C and perl preserver the offset correctly when doing '%s %z'.

So it's very clear DateTime.strptime() has to be fixed.

Patch attached.

---Files--------------------------------
0001-datetime-fix-strptime-s-z.patch (1.94 KB)


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