生年月日をDBからDATEFORMatに変換しようとしていますが、DOBフィールドにいくつかの負の値があり、オンラインのFROM_UNIXTIME計算機からチェックすると異なる結果が得られ、それをチェックすると異なる結果が得られるという問題に直面していますFROM_UNIXTIME(-957632400)
。負の値の場合は常にNULLを返します。-957632400のようなUNIX形式から日付形式を取得する方法を教えてください
2 に答える
代わりにこれを行うことができます:
FROM_UNIXTIME(0) + INTERVAL -957632400 SECOND
このFROM_UNIXTIME
関数は、TIMESTAMP
データ型の許容範囲によって制限されます。これは、標準の32ビットunsignedint範囲1970-01-01から2038-01までです。他のソフトウェアは64ビットの符号付き整数をサポートするように更新されていますが、MySQLはまだその機能を提供していません(少なくとも5.1.xでは提供されていません)。
MySQLの回避策は、より広い範囲が必要な場合(1970年1月1日より前の日付など)に、データ型を使用せず、代わりにデータTIMESTAMP
型を使用することです。DATETIME
この関数を使用してDATE_ADD
、次のように1970年1月1日から秒を減算できます。
SELECT DATE_ADD('1970-01-01 00:00:00',INTERVAL -957632400 SECOND)
注意:これらのタイプの計算を行う際には、UTCからのタイムゾーンの「オフセット」を考慮する必要があります。MySQLは、DATETIME値を、UTC( )time_zone
ではなく、現在のMySQLセッションの設定で指定されているものとして解釈します。time_zone = '+00:00'
ファローアップ:
Q:わかりました。つまり、「1970-01-01 00:00:00」より前の日付を選択すると、負の値がデータベースに保存されます。それ以外の場合は正になります。右?–ソフトジェニック
A:ええと、違います。1970年1月1日より前の日付/日時値を選択した場合、MySQLは1970年1月1日より前のDATEまたはDATETIME値を返します。1970年1月1日より前のDATEまたはDATETIME値を保存すると、MySQLは1月1日より前のDATEまたはDATETIME値を保存します。 、1970、これらのデータタイプでサポートされる許容範囲内。(0001-01-01から9999のようなもの?)
本当に大きな正と負の整数をデータベースに格納する必要がある場合は、それらをとして定義された列に格納する可能性がありますBIGINT
。
DATE列の内部表現には3バイトのストレージが必要であり、DATETIMEには8バイトのストレージが必要です(MySQLバージョン5.6.4まで。5.6.4で変更されたDATE値とDATETIME値の内部表現とストレージ)
したがって、MySQLは1970年より前の日付値を「負の整数」として保存しません。
少し考えてみると、MySQLは必要なストレージメカニズムを自由に実装できます。(そして、各ストレージエンジンは、その表現をディスクに自由にシリアル化できます。)
なぜ日付に3バイトなのですか?
MySQLのオプションの1つ(これがその方法であることを表明しているわけではありません)は、日付を年、月、日のコンポーネントに分割することです。
範囲内の整数値の表現-requires-
0 - 9999 -
14ビット0 - 12 -
4ビット0 - 31 -
5ビット
これは合計23ビットで、たまたま3バイトに収まります。これは、MySQLが1970年1月1日より前の日付値を負の整数として表す必要がないことを示しているだけなので、そうなると仮定するべきではありません。(ただし、MySQLのストレージエンジンで作業している場合は、このレベルの詳細にのみ関心があります。)
DATETIMEからUNIXタイムスタンプまで:
SELECT TIMESTAMPDIFF(SECOND, FROM_UNIXTIME(0), '1956-12-24 01:06:49');
タイムスタンプからDATETIMEまで:
SELECT DATE_ADD(convert_tz(FROM_UNIXTIME(0), @@session.time_zone,'+00:00'), INTERVAL -410914391 SECOND);