C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

時間の差をミリ秒で求める /夜叉姫 (20/11/12(Thu) 14:27) #96346
Re[1]: 時間の差をミリ秒で求める /魔界の仮面弁士 (20/11/12(Thu) 16:05) #96351
  └ Re[2]: 時間の差をミリ秒で求める /夜叉姫 (20/11/17(Tue) 08:47) #96365
    ├ Re[3]: 時間の差をミリ秒で求める /通りすがり (20/11/17(Tue) 10:15) #96366
    └ Re[3]: 時間の差をミリ秒で求める /魔界の仮面弁士 (20/11/17(Tue) 10:40) #96369


親記事 / ▼[ 96351 ]
■96346 / 親階層)  時間の差をミリ秒で求める
□投稿者/ 夜叉姫 (4回)-(2020/11/12(Thu) 14:27:46)

分類:[.NET 全般] 

SQLServerにて
ETIME が 2020-12-25 08:00:00 の時は
どうすれば求まりますか?

DECLARE @STIME DATETIME = '2020-11-11 20:00:00.000';
DECLARE @ETIME DATETIME = '2020-11-13 08:00:00.000';
--DECLARE @ETIME DATETIME = '2020-12-25 08:00:00.000';

DECLARE @DFT INT = DATEDIFF(MILLISECOND, @STIME, @ETIME) / 3;

DECLARE @TM1 DATETIME = DATEADD(MILLISECOND, @DFT * 0, @STIME);
DECLARE @TM2 DATETIME = DATEADD(MILLISECOND, @DFT * 1, @STIME);
DECLARE @TM3 DATETIME = DATEADD(MILLISECOND, @DFT * 2, @STIME);
DECLARE @TM4 DATETIME = DATEADD(MILLISECOND, @DFT * 3, @STIME);

SELECT @TM1, @TM2, @TM3, @TM4
[ □ Tree ] 返信 編集キー/

▲[ 96346 ] / ▼[ 96365 ]
■96351 / 1階層)  Re[1]: 時間の差をミリ秒で求める
□投稿者/ 魔界の仮面弁士 (2910回)-(2020/11/12(Thu) 16:05:25)
No96346 (夜叉姫 さん) に返信
> 分類:[.NET 全般] 
> SQLServerにて

であれば、[.NET 全般]ではなく、[データベース全般]が適切かと。
あるいは [その他の言語] とか。


> DECLARE @STIME DATETIME = '2020-11-11 20:00:00.000';
> DECLARE @ETIME DATETIME = '2020-11-13 08:00:00.000';
> --DECLARE @ETIME DATETIME = '2020-12-25 08:00:00.000';
> DECLARE @DFT INT = DATEDIFF(MILLISECOND, @STIME, @ETIME) / 3;

MILLISECOND を指定されていますが、DATETIME 型の精度は 1/1000 秒ではありません。
秒未満の小数点以下(3 桁目まで)は、「.xx0」「.003」「.007」のいずれかなのでご注意を。

ミリ秒精度を求めるなら、DATETIME2 型が使えます。(こちらは 100 ナノ秒精度)

…それはさておき。


DATEDIFF は INT 精度なので、
MILLISECOND 指定で求められる範囲は
24日20時間31分23.647 が上限です。

これを SECOND 指定に切り替えれば、68年分ぐらいまで耐えられるでしょう。


とはいえ、今回欲しいのは「ミリ秒」の差なのですよね。

もしも MILLISECOND での指定が必要であれば、
 DECLARE @DFT BIGINT = DATEDIFF_BIG(MILLISECOND, @STIME, @ETIME);
という方法はあります。


ただし、対応する DATEADD_BIG 関数があるわけではありませんので、
その点は注意が必要です。(DATEADD は INT 精度)


本当にミリ秒指定での算出が必要なら、処理を分けて、
「日数差」と「日未満の時刻差」を別々に演算してみてください。
[ 親 96346 / □ Tree ] 返信 編集キー/

▲[ 96351 ] / ▼[ 96366 ] ▼[ 96369 ]
■96365 / 2階層)  Re[2]: 時間の差をミリ秒で求める
□投稿者/ 夜叉姫 (6回)-(2020/11/17(Tue) 08:47:42)
2020/11/17(Tue) 09:33:39 編集(投稿者)

No96351 (魔界の仮面弁士 さん) に返信

遅くなって申し訳ありません。

DECLARE @STIME DATETIME = '2020-01-01 0:0:0.000';
DECLARE @ETIME DATETIME = '2020-12-31 23:59:59.999';

DECLARE @DFT BIGINT = DATEDIFF_BIG(MILLISECOND, @STIME, @ETIME);

SELECT @DFT

上記実行すると
以下のエラーメッセージが表示されます。

メッセージ 195、レベル 15、状態 10、行 4
'DATEDIFF_BIG' は 組み込み関数名 として認識されません。
メッセージ 137、レベル 15、状態 2、行 6
スカラー変数 "@DFT" を宣言してください。

追記
SQLServer 2016 で対応みたいでした。
使用している SQLServer は 2012 なので使えませんでした。
[ 親 96346 / □ Tree ] 返信 編集キー/

▲[ 96365 ] / 返信無し
■96366 / 3階層)  Re[3]: 時間の差をミリ秒で求める
□投稿者/ 通りすがり (5回)-(2020/11/17(Tue) 10:15:24)
No96365 (夜叉姫 さん) に返信
バージョン低いなら基礎構文で組み上げるしか無い訳で
その情報は全部出てると思うんだけど、全部試したのかな?

DECLARE @STIME DATETIME2 = '2020-12-31 0:0:0.000';
DECLARE @ETIME DATETIME2 = '2020-12-31 23:59:59.999';
SELECT DATEDIFF(MS, @STIME, @ETIME) AS [列1]
[ 親 96346 / □ Tree ] 返信 編集キー/

▲[ 96365 ] / 返信無し
■96369 / 3階層)  Re[3]: 時間の差をミリ秒で求める
□投稿者/ 魔界の仮面弁士 (2913回)-(2020/11/17(Tue) 10:40:50)
No96365 (夜叉姫 さん) に返信
> 2020/11/17(Tue) 08:55:02 編集(投稿者)
>
> DECLARE @ETIME DATETIME = '2020-12-31 23:59:59.999';

No96351 でも述べましたが、上記の記述には問題があります。

DATETME 型の精度においては、上記の末尾は .997 または .000 の何れか近いに丸められるため、
結果的に、下記の @ETIME2 相当の時刻として保持されることになります。

DECLARE @ETIME1 DATETIME = '2020-12-31 23:59:59.997';
DECLARE @ETIME2 DATETIME = '2021-01-01 00:00:00.000';


秒未満の値を小数点以下 3 桁精度で保持したいのであれば、このようにします。

DECLARE @ETIME DATETIME2(3) = '2020-12-31 23:59:59.997';



> DECLARE @DFT BIGINT = DATEDIFF_BIG(MILLISECOND, @STIME, @ETIME);
> SQLServer 2016 では対応していないみたいでした。

DATEDIFF_BIG は SQL Server 2016 から搭載された物のはずなのですが…。(2014 や 2012 では非対応)
https://docs.microsoft.com/ja-jp/sql/t-sql/functions/datediff-big-transact-sql?view=sql-server-ver15

当方も SQL Server 2016 ですが、提示されたコードをそのまま貼りつけて実行すると、
DATEDIFF_BIG によって、31622400000 という値が得られました。

「SELECT @@VERSION」の結果が、SQL Server 2016 を指しているにもかかわらず、
『'DATEDIFF_BIG' は 組み込み関数名 として認識されません。』が表示されるのでしょうか?


もしも DATEDIFF のままで処理するなら、
>>> 処理を分けて、「日数差」と「日未満の時刻差」を別々に演算
を行ってみてください。


-- 両者の差は、364日間12時間34分56秒790
DECLARE @S_DateTime DATETIME2(3) = '2020-01-01 23:59:59.999';
DECLARE @E_DateTime DATETIME2(3) = '2020-12-31 12:34:56.789';

DECLARE @SDATE DATE = CAST(@S_DateTime AS DATE);
DECLARE @EDATE DATE = CAST(@E_DateTime AS DATE);
DECLARE @STIME TIME(3) = CAST(@S_DateTime AS TIME);
DECLARE @ETIME TIME(3) = CAST(@E_DateTime AS TIME);

-- 日数部の差。時刻部を切り捨てているので、実際の日数差とは ±24時間弱の誤差が出る。
DECLARE @DAYS INT = DATEDIFF(DAY, @SDATE, @EDATE); -- 今回は 365日間

-- ミリ秒の部の差。-86,399,999 ≦ @MSEC ≦ 86,399,999 の範囲になるハズ。
DECLARE @MSEC INT = DATEDIFF(MILLISECOND, @STIME, @ETIME); -- 今回は -41,103,210 ミリ秒
select @STIME,@ETIME
-- トータルのミリ秒差。
DECLARE @TOTAL_MSEC BIGINT = @DAYS * CAST(86400000 AS BIGINT) + @MSEC

/*
-- マイナス時刻を補正する場合
IF @MSEC < 0
BEGIN
SET @DAYS = @DAYS - 1
SET @MSEC = @MSEC + 86400000
END
*/

-- 365 | -41103210 | 31494896790 あるいは
-- 364 | +45296790 | 31494896790
SELECT @DAYS, @MSEC, @TOTAL_MSEC;

[ 親 96346 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -