質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

1回答

1211閲覧

JSの時間遷移について

Chandler_Bing

総合スコア673

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

0クリップ

投稿2019/01/31 14:13

以前にも似たような質問をさせて頂きました。現在新たな問題があります。このプログラムの挙動としてはオークションの終了時間をDBから取得し(現在はテストのため手打ち)残り時間を表示させ、1時間を切っていれば1秒更新でタイマーを表示するというプログラムです。残り時間が0になればJSにて'このオークションは終了しました'と表示させ、ページに来た時点で終了していればPHPで同じ文字を表示します。

問題(例)
現在時刻(仮)2019年1月31日20時30分00秒
手打ち時間(仮)2019年1月31日20時31分00秒

現在時刻が上記のとき手打ち時間を上記のようにすると、きちんと1秒カウントダウンが表示され時間が0になると'このオークションは終了しました'と表示されます。しかしこの段階でページ更新をすると、本来はint(1)のところに入るはずですが、int(0)の部分の'このオークションは終了しました'が表示されます。残り時間がきた後にページを読み込むのですから、また上から手打ち時間を読み込み、それがすでに過去になっているはずなので、$endがtrueになると思ったのですが何故そのように動かないのでしょうか。

PHP

1<?php 2//手打ち時間 3$end = false; 4$year = 2019; 5$month = 1; 6$day = 31; 7$hour = 22; 8$minute = 54; 9$second = 00; 10$month1 = 0; 11$datetime = new DateTime("$year/$month/$day $hour:$minute:$second"); 12$current = new DateTime('now'); 13$diff= $current->diff($datetime); 14var_dump($diff); 15if ($diff ->invert == 1) { 16 $end = true; 17} 18 19?> 20 21<!DOCTYPE html> 22<html lang="en" dir="ltr"> 23 24<head> 25 <meta charset="utf-8"> 26 <title></title> 27 <link rel="stylesheet" href="styles.css"> 28 <script src="../Shopping/jquery-3.3.1.min.js"></script> 29</head> 30 31<body> 32 33 <div class="dobid"> 34 35 <?php if ($end == false): ?> 36 <!-- 確認のvar_dump --> 37 <?php var_dump(0); ?> 38 <div class="bid"> 39 <a href="#">入札する</a> 40 <span class="time">残り</span> 41 </div> 42 43 <p id="clone">このオークションは終了しました</p> 44 45 <?php elseif ($end == true): ?> 46 <!-- 確認のvar_dump --> 47 <?php var_dump(1); ?> 48 <p>このオークションは終了しました</p> 49 50 <?php endif ?> 51 52 </div> 53 54</body> 55 56<script> 57 var end = '<?php echo $end; ?>'; 58 var year = '<?php echo $year; ?>'; 59 var month = '<?php echo $month; ?>'; 60 var day = '<?php echo $day; ?>'; 61 var hour = '<?php echo $hour; ?>'; 62 var minute = '<?php echo $minute; ?>'; 63 64 var cutoff = new Date(); 65 cutoff.setFullYear(year); 66 cutoff.setMonth(month - 1); 67 cutoff.setDate(day); 68 cutoff.setHours(hour); 69 cutoff.setMinutes(minute); 70 cutoff.setSeconds(00); 71 72 var countdown = function(cutoff) { 73 var now = new Date(); 74 var rest = cutoff.getTime() - now.getTime(); 75 var sec = Math.floor(rest / 1000) % 60; 76 var min = Math.floor(rest / 1000 / 60) % 60; 77 var hours = Math.floor(rest / 1000 / 60 / 60) % 24; 78 var days = Math.floor(rest / 1000 / 60 / 60 / 24); 79 var count = [days, hours, min, sec]; 80 return count; 81 } 82 83 var recalc = function() { 84 var count = countdown(cutoff); 85 if (count[2] < 0) { 86 $('.bid').hide(); 87 $('#clone').fadeIn(); 88 } else { 89 var time = count[1] + '時間' + count[2] + '分' + count[3] + '秒'; 90 $('.time').text(time); 91 refresh(); 92 } 93 } 94 95 var refresh = function() { 96 setTimeout(recalc, 1000); 97 } 98 99 if (end == false) { 100 var count = countdown(cutoff); 101 102 if (count[2] < 0) { 103 $('.bid').hide(); 104 $('#clone').fadeIn(); 105 } else if (count[1] < 1) { 106 recalc(); 107 } else { 108 var time = count[1] + '時間' + count[2] + '分' + count[3] + '秒'; 109 $('.time').text(time); 110 } 111 } 112</script> 113 114</html>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tabuu

2019/02/01 01:42

微妙に質問が分かりづらいです。 >しかしこの段階でページ更新をすると、本来はint(1)のところに入るはずですが、int(0)の部分の'このオークションは終了しました'が表示されます。 int(1)やint(0)とは何のことでしょうか?ソースコードには無いようです。 >残り時間がきた後にページを読み込むのですから、また上から手打ち時間を読み込み、それがすでに過去になっているはずなので、$endがtrueになると思ったのですが何故そのように動かないのでしょうか。 $endがtrueになっているので'このオークションは終了しました'が表示されて正解ではないのでしょうか?
Chandler_Bing

2019/02/01 01:53

ありがとうございます。 コメントアウトがあると思いますが、vardunpで数字の0と1を表示しています。 数字が0の時はカウントダウン中には時間が来た場合、 数字が1の時は、ページに来た時点ですでにオークションが終了してしている場合です。
tabuu

2019/02/01 02:14

$datetime,$current,$diff のそれぞれ値もvar_dump等で想定している内容か確認してはいかがでしょうか。 ちなみにint(0)の方もint(1)の方も両方に「このオークションは終了しました」がありますが $endの値ではなく別の問題ということはないでしょうか。
Chandler_Bing

2019/02/01 02:25

ありがとうございます。両方にあります。もちろん意図的にです。 ページに来た時点で終了していれば 1の方のメッセージが表示され 残り時間があればJSに行きます。そしてタイマーを表示します。そして残りが0になればhideとfadeInを使い同じメッセージを出します。 質問としては残り時間が0になり、 オークションが終了しました。 というメッセージが表示される時は int(0)ですが、その段階でページ更新をすると、当然ページに来た段階でオークションが終了してるので int(1)のメッセージがでるというのが私の予測だったのですが、そのように動きません。
Lhankor_Mhy

2019/02/01 02:40

キャッシュはどうなっていますか?
Chandler_Bing

2019/02/01 02:43

ありがとうございます。 キャッシュもクリアにして行いましたが、同じです。
Lhankor_Mhy

2019/02/01 02:51

var_dump($diff); の結果はどうでしたか? あと、jsの if (end == false) { は真になることがないと思うのですが、それはそれでいいですか?
Chandler_Bing

2019/02/01 03:26

ありがとうございます。 イコールが3ついるということでしょうか。
Lhankor_Mhy

2019/02/01 05:18

いえ、 var end = '<?php echo $end; ?>'; とありますから、 変数endは、文字列です。 javascript で false に型キャストされる文字列は、おそらく '' だけだと思います。 なので、 echo $end; で何も出力されない場合にのみ、end == false が真になります。
Lhankor_Mhy

2019/02/01 05:18

それと、 var_dump($diff); の結果はどうでしたか?
Chandler_Bing

2019/02/01 11:18

ありがとうございます。 if (end == false)の場合のみカウントダウンを実行するようにしており、実感が過去の場合はタイマーが作動するので、条件分岐はうまくいっていると思うのですが、、、違いますかね。 現在時刻(仮)2019年2月1日20時13分00秒 手打ち時間(仮)2019年2月1日20時10分00秒 の場合は object(DateInterval)#3 (16) { ["y"]=> int(0) ["m"]=> int(0) ["d"]=> int(0) ["h"]=> int(8) ["i"]=> int(56) ["s"]=> int(30) ["f"]=> float(-0.152244) ["weekday"]=> int(0) ["weekday_behavior"]=> int(0) ["first_last_day_of"]=> int(0) ["invert"]=> int(0) ["days"]=> int(0) ["special_type"]=> int(0) ["special_amount"]=> int(0) ["have_weekday_relative"]=> int(0) ["have_special_relative"]=> int(0) } となりました。
Lhankor_Mhy

2019/02/02 00:50

なるほど、では私の勘違いでしょうね。 invert が 0 になっていると思うのですが、これはこれで合っているのですか?
Chandler_Bing

2019/02/02 09:02

ありがとうございます。あっていません。1の時に日付が過去になります。 日付を5分前、10分前等にするとPHPでは過去であると判定されず、一旦JSに飛びそこでは過去と判定されますので、挙動は問題がないといえばないのですが、PHP(diffメソッド)では5分前、10分前は過去にならないのでしょうか。
Lhankor_Mhy

2019/02/02 09:04

PHPは詳しくないのでアレなのですが、タイムゾーンの影響のような気がしますね。 $datetime と $current の var_dump を取ってみればはっきりするかと思いますが。
退会済みユーザー

退会済みユーザー

2019/03/13 11:31

回答は出そろってると思います 解決済みにするか、してないなら回答にコメントするなりしてくださいなー
退会済みユーザー

退会済みユーザー

2019/03/13 12:04

回答は出そろってると思います 解決済みにするか、してないなら回答にコメントするなりしてくださいなー
guest

回答1

0

ベストアンサー

サーバーにapiを用意してajaxでアクセスして終了までの秒数などを
返してもらうようにすればよいのでは?
1分サイクルくらいでapiにアクセスして誤差を調整するとよいでしょう。
1秒単位で終了をジャッジするのは危険なのでやめておいた方が賢明です。
(1秒前だったの大丈夫だとおもったのに終了していたとかクレームの元)

sample

たとえばid=100の商品について問い合わせに終了時刻と残り時間を返す

  • api.php

PHP

1<?PHP 2$id=filter_input(INPUT_GET,"id"); 3if($id==="100"){ 4 $endStr="2019/02/01 12:00"; 5 $end=strtotime($endStr); 6 $now=time(); 7 print json_encode([ 8 "end_datetime"=>"2019/02/01 12:00", 9 "remaining_time"=>$end>$now?$end-$now:0, 10 ]); 11 exit; 12} 13print 0;

これをjsで1分毎に読む

javascript

1<script> 2window.addEventListener('DOMContentLoaded', function(e){ 3 var func=function(){ 4 var xhr = new window.XMLHttpRequest(); 5 var url="api.php"; 6 var data="id=100"; 7 xhr.open("get", url+"?"+data); 8 xhr.send(null); 9 xhr.onreadystatechange=function(){ 10 if(( xhr.readyState == 4 ) && ( xhr.status == 200 )){ 11 console.log(JSON.parse(xhr.responseText)); 12 } 13 }; 14 } 15 func(); 16 var timerId=setInterval(func,60000); 17}); 18</script>

ajaxはjQueryなどでやるほうがラクなんだけどとりあえずピュアなjsで書いてあります

投稿2019/02/01 02:43

編集2019/02/01 03:11
yambejp

総合スコア114585

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Chandler_Bing

2019/02/01 02:45

ありがとうございます。 具体的にどのように実行できるか サンプルコードをご提示出して頂けますか。 答えはいりません。
think49

2019/02/01 04:12

@YutaNkaiさん 答え不要ということですが、「答えではないソースコード」とは何でしょう?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問