SO 440061には、時間の 12 時間表記と 24 時間表記の間の変換 (この変換の反対) に関する有用な情報があることに注意してください。午前 12 時 45 分は午前 1 時 15 分より 30 分前なので、これは些細なことではありません。
次に、Informix (IDS — Informix Dynamic Server) バージョン 7.31 が 2009 年 9 月 30 日に最終的にサービスを終了したことに注意してください。サポートされていない製品です。
バージョン番号をより正確にする必要があります。たとえば、7.30.UC1 と 7.31.UD8 の間にはかなりの違いがあります。
ただし、必要に応じてTO_CHAR()関数を使用して時刻をフォーマットできるはずです。これはIDS 12.10 Information Center に関するものですが、7.31 でも使用できると思います (必ずしも 7.30 ではなく、過去 10 年間ほとんど使用していなかったはずです)。
24 時間制の '%R' 形式指定子があります。また、' GL_DATETIME 'も参照します。ここで、'%I' は 12 時間制の時刻を示し、'%p' は午前/午後のインジケータを示します。これを検証するために、IDS の 7.31.UD8 インスタンスも見つけました。
select to_char(datetime(2009-01-01 16:15:14) year to second, '%I:%M %p')
from dual;
04:15 PM
select to_char(datetime(2009-01-01 16:15:14) year to second, '%1.1I:%M %p')
from dual;
4:15 PM
質問を読み直すと、実際には 0000..2359 の範囲の SMALLINT 値があり、それらを変換する必要があることがわかります。Informix にはそのような値を格納するための型 (DATETIME HOUR TO MINUTE) があることをよく指摘しますが、ディスク上で 2 バイトではなく 3 バイトを占有するため、SMALLINT 表記ほどコンパクトではありません。
Steve Kass は、SQL Server の表記法を示しました。
select
cast((@milTime/100+11)%12+1 as varchar(2))
+':'
+substring(cast((@milTime%100+100) as char(3)),2,2)
+' '
+substring('ap',@milTime/1200%2+1,1)
+'m';
正確な時間を取得するためのトリックは巧妙です - ありがとうスティーブ!
IDS 11.50 の Informix に変換されます。テーブルは次のとおりです。
CREATE TEMP TABLE times(begin_tm SMALLINT NOT NULL);
SELECT begin_tm,
(MOD(begin_tm/100 + 11, 12) + 1)::VARCHAR(2) || ':' ||
SUBSTRING((MOD(begin_tm, 100) + 100)::CHAR(3) FROM 2) || ' ' ||
SUBSTRING("ampm" FROM (MOD((begin_tm/1200)::INT, 2) * 2) + 1 FOR 2)
FROM times
ORDER BY begin_tm;
FROM と FOR を使用した SUBSTRING 表記は、標準の SQL 表記です。奇妙ですが、そうです。
結果の例:
0 12:00 am
1 12:01 am
59 12:59 am
100 1:00 am
559 5:59 am
600 6:00 am
601 6:01 am
959 9:59 am
1000 10:00 am
1159 11:59 am
1200 12:00 pm
1201 12:01 pm
1259 12:59 pm
1300 1:00 pm
2159 9:59 pm
2200 10:00 pm
2359 11:59 pm
2400 12:00 am
注意: 値 559 から 601 がリストに含まれているのは、整数へのキャストがない場合に切り捨てではなく丸めの問題に遭遇したためです。
現在、これは IDS 11.50 でテストされています。IDS 7.3x にはキャスト表記がありません。ただし、それは問題ではありません。次のコメントはそれに対処するつもりでした...
条件などを使わずにSQLで式を書く方法の演習として、これは興味深いですが、スイート全体で誰かがそれを2回以上書いた場合、私はそれらをモジュール化の欠如のために撃ちます. 明らかに、これにはストアド プロシージャが必要です。また、ストアド プロシージャには (明示的な) キャストやその他のトリッキーは必要ありませんが、割り当てによって暗黙的なキャストが強制されます。
CREATE PROCEDURE ampm_time(tm SMALLINT) RETURNING CHAR(8);
DEFINE hh SMALLINT;
DEFINE mm SMALLINT;
DEFINE am SMALLINT;
DEFINE m3 CHAR(3);
DEFINE a3 CHAR(3);
LET hh = MOD(tm / 100 + 11, 12) + 1;
LET mm = MOD(tm, 100) + 100;
LET am = MOD(tm / 1200, 2);
LET m3 = mm;
IF am = 0
THEN LET a3 = ' am';
ELSE LET a3 = ' pm';
END IF;
RETURN (hh || ':' || m3[2,3] || a3);
END PROCEDURE;
Informix の '[2,3]' 表記は、部分文字列演算子のプリミティブ形式です。プリミティブな理由は、(まだ私にはわからない理由で)添字はリテラル整数(変数でも式でもない)でなければならないためです。ここではたまたま役に立ちます。一般的に、それはイライラします。
このストアド プロシージャは、実際に使用できるすべてのバージョンの Informix (OnLine 5.x、SE 7.x、IDS 7.x または 9.x、10.00、11.x、12.x) で動作するはずです。
式とストアド プロシージャの等価性 (マイナー バリアント) を説明するには、次のようにします。
SELECT begin_tm,
(MOD(begin_tm/100 + 11, 12) + 1)::VARCHAR(2) || ':' ||
SUBSTRING((MOD(begin_tm, 100) + 100)::CHAR(3) FROM 2) ||
SUBSTRING(' am pm' FROM (MOD((begin_tm/1200)::INT, 2) * 3) + 1 FOR 3),
ampm_time(begin_tm)
FROM times
ORDER BY begin_tm;
結果は次のようになります。
0 12:00 am 12:00 am
1 12:01 am 12:01 am
59 12:59 am 12:59 am
100 1:00 am 1:00 am
559 5:59 am 5:59 am
600 6:00 am 6:00 pm
601 6:01 am 6:01 pm
959 9:59 am 9:59 pm
1000 10:00 am 10:00 pm
1159 11:59 am 11:59 pm
1200 12:00 pm 12:00 pm
1201 12:01 pm 12:01 pm
1259 12:59 pm 12:59 pm
1300 1:00 pm 1:00 pm
2159 9:59 pm 9:59 pm
2200 10:00 pm 10:00 pm
2359 11:59 pm 11:59 pm
2400 12:00 am 12:00 am
このストアド プロシージャは、ACE レポート内の単一の SELECT ステートメントで何度も使用できるようになりました。
[元の投稿者からのコメントの後、機能しないことについて... ]
IDS 7.31 は、MOD() 関数に渡される非整数値を処理しません。したがって、除算は明示的な整数変数に格納する必要があります。したがって、次のようになります。
CREATE PROCEDURE ampm_time(tm SMALLINT) RETURNING CHAR(8);
DEFINE i2 SMALLINT;
DEFINE hh SMALLINT;
DEFINE mm SMALLINT;
DEFINE am SMALLINT;
DEFINE m3 CHAR(3);
DEFINE a3 CHAR(3);
LET i2 = tm / 100;
LET hh = MOD(i2 + 11, 12) + 1;
LET mm = MOD(tm, 100) + 100;
LET i2 = tm / 1200;
LET am = MOD(i2, 2);
LET m3 = mm;
IF am = 0
THEN LET a3 = ' am';
ELSE LET a3 = ' pm';
END IF;
RETURN (hh || ':' || m3[2,3] || a3);
END PROCEDURE;
これは、Solaris 10 上の IDS 7.31.UD8 でテストされ、正しく機能しました。報告された構文エラーがわかりません。しかし、バージョンに依存する外部の可能性があります。念のため、バージョン番号とプラットフォームを報告することは常に重要です。さまざまなことが機能した場所を注意深く記録していることに注意してください。それは偶然でもなく、単なるこだわりでもなく、長年の経験に基づいています。