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

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

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

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

4回答

2775閲覧

Javascript: カレンダーに関する繰り返し処理について(休みを設けるプログラム)

rails_ruby

総合スコア87

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2019/02/11 13:47

編集2019/02/12 04:35

前提/実現したいこと

for-ifを使って意図したタイミングと処理を繰り返し処理をしたいです。
具体的にはfor文を使って下記の日程の時のみ繰り返し処理を行えるようにしたい。

  • 2019-01-01
  • 2019-01-08
  • 2019-01-15
  • 2019-01-22
  • 2019-01-29...etc

イメージ

js

1for(let i=i;i<365;i++){ 2 if(dates / 7){ 3 処理 4 } 5}

発生している問題・エラーメッセージ / 試したこと

プログラミング知識が浅いため、どの処理を繰り返し処理させればいいか分からずfor文を回したら2018-01-01の処理がひたすら回されました。

実際のコード
この時はif文を入れていないので2018-01-01の処理が30回実行されました。

javascript

1for(let i=0;i<=30;i++){ 2 var m=Array((d2(i).getTime()-d1.getTime())/1000/60/offset+1).fill(null).map(function(x,y){ 3 return (new Date(d1.getTime()+1000*60*offset*y)).toISOString().substr(0,16); 4 }); 5 [].push.a

該当のソースコード

html

1<input type="date" value="2019-01-01" id="dates"> <!-- 火曜日 --> 2<input type="time" value="08:00" id="time_start"> <!-- 変更前: 00:00--> 3<input type="time" value="10:00" id="time_finish"><!-- 変更前: 23:30 -->

js

1<script> 2const BUSY = [ 3 '2019-02-12T10:00', 4 '2019-02-09T23:30' 5]; 6window.addEventListener('DOMContentLoaded', function(){ 7 document.querySelector('#btn').addEventListener('click',function(){ 8 var offset=30; 9 var d0=document.querySelector('#dates').value; 10 var t1=document.querySelector('#time_start').value; 11 var t2=document.querySelector('#time_finish').value; 12 var d1=new Date(d0+" "+t1);d1.setTime(d1.getTime()+1000*60*60*9); 13 var d2=new Date(d0+" "+t2);d2.setTime(d2.getTime()+1000*60*60*9); 14 var m=Array((d2.getTime()-d1.getTime())/1000/60/offset+1).fill(null).map(function(x,y){ 15 return (new Date(d1.getTime()+1000*60*offset*y)).toISOString().substr(0,16); 16 }); 17 [].push.apply(BUSY,m); 18 console.log(BUSY); 19 }); 20}); 21</script>

補足情報(FW/ツールのバージョンなど)

以前の質問に関連しているので、参照していただけるともう少しコードが見れるかと思います。
以前の質問
リンク先でコードを動かすことができます
JavaScript

追記

文字数の制約上、実際の処理に関わる部分のみを抜粋しています。
(練習で色々な処理を試しているので現在のコードがぐちゃぐちゃで載せるに載せないのも理由の一つです...)

forを使わないときの処理内容
d0,t1,t2の変数において、querySelectorを用いてinputのvalueを取得しています。
取得した、valueを変数d1,d2でdateとtimeを結合?しています。
そしてmではtime_startからtime_finishまでの時間帯を30分おきに配列にしています。
そして、本質問内にはありませんが定数BUSYにpushしています。
console.logで見ると下記のようになります。

コンソール

["2019-01-01T08:00","2019-01-01T08:30","2019-01-01T09:00","2019-01-01T09:30","2019-01-01T10:00"]

for文を使った場合 ← ここを実現したいです。

1週目
["2019-01-01T08:00","2019-01-01T08:30","2019-01-01T09:00","2019-01-01T09:30","2019-01-01T10:00",
2週目
"2019-01-08T08:00","2019-01-08T08:30","2019-01-08T09:00","2019-01-08T09:30","2019-01-08T10:00",
3週目
"2019-01-15T08:00","2019-01-15T08:30","2019-01-15T09:00","2019-01-15T09:30","2019-01-15T10:00",
4週目
"2019-01-22T08:00","2019-01-22T08:30","2019-01-22T09:00","2019-22-01T09:30","2019-01-22T10:00"
5週目
...etc
]

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

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

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

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

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

kei344

2019/02/11 13:55

どの情報をつかって、どういう値を導きたいのかをもう少し丁寧に詳細に追記してください。
rails_ruby

2019/02/11 14:30

私なりにできるだけわかりやすく必要であろう情報をすべて、質問に追記させて頂きました。 この他に、何か情報が必要でしょうか?必要であれば可能な限り(文字数制限が許す限り)追記させて頂きたいと思います。 一応ですが、以前の質問に関連した質問なので以前、投稿した質問のリンクをつけてありますのでご参照いただければと思います。
kei344

2019/02/11 14:36

「実際のコード」の「d2(i)」はエラーになりませんでしたか?そのコード前後のコードも再現できる程度に提示いただけませんか?
rails_ruby

2019/02/11 14:43

ご指摘していただいた「d2(i)」は繰り返し処理をなんとかしようとして色々いじった過程の処理をそのまま質問に投稿したので、d2に(i)を入れるとエラーが起きます。 なので(i)がないd2の時はエラーはなく2018-01-01がひたすら繰り返されていきます。 わかりました。もう少し追記できる範囲で追記したいと思います。
rails_ruby

2019/02/11 14:52

実行したい処理に関わるコードを全て追記しましたので、追記したコードで試していただけると検証できるかと思います。
kei344

2019/02/11 15:13

追記されたコードには例えば「toISOString」が無いので、「実際のコード」とは違うコードのようです。また提示されたコードはHTML上に特定の要素が無いと動かないようなので、関係が有るコードなのかもわかりませんでした。 https://jsfiddle.net/5js2wvhx/ 何度も書き換えてもらって申し訳ないのですが、私には解決できない質問のようです、お騒がせしました、すみません。
rails_ruby

2019/02/11 15:22

https://jsfiddle.net/qfkowzb5/13/ 上記のリンクにgoogleのディベロッパーツールで試していただけないでしょうか? ボタンを押すと配列が生成されるかと思います。
guest

回答4

0

javascript

1<!DOCTYPE html> 2<html lang="ja"> 3<meta charset="utf-8"> 4<style> 5#calendar td { text-align: center; font-size: 80%; } 6#calendar .sun { background: rgba(255,0,0,.1); color: rgba(255,0,0,1); } 7#calendar .sat { background: rgba(0,0,255,.1); color: rgba(0,0,255,1); } 8#calendar .button { color: blue; text-decoration: underline; } 9#calendar .button:hover { color: red; } 10#calendar table, #calendar td { border: 1px gray solid; padding: 4px;} 11#calendar table { border-collapse: collapse; border-spacing: 0; } 12#calendar tbody tr:nth-of-type(odd) { background: rgba(0,0,0,.05); } 13</style> 14 15<body> 16<div id="calendar"></div> 17<input type="text" class= "text" id="acdn-target" onselect="click_date" readonly> 18 19 20 21<script> 22{ 23 const 24 day_name = [ 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'], 25 day_jname = ['(Sun.)', '(Mon.)', '(Tue.)', '(Wed.)', '(Thurs.)', '(Fri.)', '(Sat.)'], 26 doc = document, 27 DEF_OPTION = { }; 28 29 const 30 A = (e, ...a) => a.map (a => e.appendChild (doc.createElement (a))), 31 B = (d, n) => d.setDate (d.getDate () + n), 32 C = d => [d.getFullYear (), '年', d.getMonth () + 1 , '月'].join (''), 33 D = d => [('0' + d.getHours ()).slice (-2), ('0' + d.getMinutes ()).slice (-2)].join (':'), 34 E = (e, d) => { 35 let 36 [a,,b] = A (e, 'label', 'br', 'label'), 37 w = d.getDay () ; 38 a.textContent = d.getDate (); 39 b.textContent = day_jname[w]; 40 e.classList.add (day_name[w]); 41 }, 42 F = d => { 43 let m = d.getMonth (); 44 return [0,31,59,90,120,151,181,212,243,273,304,334][m] + d.getDate() - 1 + 45 (new Date (d.getFullYear (), m + 1,0) === 29 && 0 < m); 46 }, 47 G = ary => ary.reduce ((a, b) => { 48 let 49 c = typeof b === 'string' ? new Date (b +':00.000+09:00'): b, 50 d = D (c); 51 if (! (d in a)) a[d] = []; 52 a[d][F(c)] = true; 53 return a; 54 }, { }) 55 , 56 H = d => new Date (d.getFullYear (), d.getMonth (), d.getDate ()), 57 I = d => [('0' + d.getUTCHours ()).slice (-2), ('0' + d.getUTCMinutes ()).slice (-2)].join (':'); 58 59 60 //_____________ 61 62 class Shedule { 63 constructor (date = new Date, range = 7, plan = [], option = DEF_OPTION) { 64 this.current = H (date); 65 this.date = H (date); 66 this.range = range; 67 this.plan = G (plan); 68 this.table = document.createElement ('table'); 69 this.option = Object.assign ({}, option); 70 71 this.remake (); 72 } 73 74 75 add (day = this.range) { 76 let d = H (this.current); 77 d.setDate (d.getDate () + day); 78 if (+this.date <= +d) { 79 this.current = d; 80 this.remake (); 81 } 82 } 83 84 85 setHoliday (dayNo) { 86 let 87 year = this.current.getFullYear (), 88 start = new Date (year, 0, 1), 89 end = new Date (year, 12, 1), 90 current = new Date (start), 91 92 b = new Date (Date.UTC (1970,0,1, 9, 0)),//列のスタート時間 93 e = new Date (Date.UTC (1970,0,1,11, 30)),//列の終了時間 94 s = new Date (Date.UTC (1970,0,1, 0,30));//列の感覚調整時間 95 96 current.setDate (7 - current.getDate () + dayNo); 97 98 for (; current < end; current.setDate (current.getDate () + 7)) { 99 let idx = F (current); 100 101 for (let c = b; c < e; c = new Date (+s + (+c))) { 102 let key = I (c); 103 if (! this.plan[key]) 104 this.plan[key] = [ ]; 105 this.plan[key][idx] = true; 106 } 107 } 108 109 this.remake (); 110 } 111 112 113 remake () { 114 this.prev_btn = this.next_btn = null; 115 let t = this.table; 116 [...t.childNodes].forEach (e => e.remove ()); 117 118 let 119 h = t.createTHead (), 120 tr0 = h.insertRow (-1), 121 tr1 = h.insertRow (-1), 122 d = H (this.current), 123 s = tr0.insertCell (-1), 124 c = 1, 125 m = d.getMonth (); 126 127 for (let i = 0; i < this.range; i++, c++, B (d, 1)) { 128 let td = tr1.insertCell (-1); 129 if (m !== d.getMonth ()) { 130 s.colSpan = c - 1; 131 s = tr0.insertCell (-1); 132 m = d.getMonth (); 133 c = 1; 134 } 135 s.textContent = C (d); 136 E (td, d); 137 } 138 s.colSpan = c - 1; 139 140 let e = tr0.insertCell (0); 141 e.textContent = '前の一週間'; 142 e.classList.add ('button'); 143 e.rowSpan = 2; 144 this.prev_btn = e; 145 146 e = tr0.insertCell (-1); 147 e.textContent = '次の一週間'; 148 e.classList.add ('button'); 149 e.rowSpan = 2; 150 this.next_btn = e; 151 152 //__ 153 let 154 begin = new Date (Date.UTC (1970,0,1, 9, 0)),//列のスタート時間 155 end = new Date (Date.UTC (1970,0,1,11, 30)),//列の終了時間 156 step = new Date (Date.UTC (1970,0,1, 0,30)),//列の感覚調整時間 157 o = F (this.current), 158 rst = [ ]; 159 160 for (let d = begin; d < end; d = new Date (+step + (+d))) { 161 let 162 a = new Array (this.rangi), 163 b = I (d), 164 c = this.plan[b] || []; 165 166 for (let i = 0; i < this.range; i++) 167 a[i] = c[o + i] ? '-' : '◎'; 168 169 rst.push ([b, ...a, b]); 170 } 171 172 let [tb] = A (t, 'tbody'); 173 rst.forEach (r => { 174 let tr = tb.insertRow (-1); 175 r.forEach (c => tr.insertCell (-1).textContent = c) 176 }); 177 } 178 179 180 handleEvent (event) { 181 let t = event.target; 182 if (t === this.prev_btn) this.add (-this.range); 183 if (t === this.next_btn) this.add (this.range); 184 185 let cbfunc = this.option.handleEvent; 186 if ('function' === typeof cbfunc) 187 cbfunc.call (this, event); 188 } 189 190 } 191 192 this.Shedule = Shedule; 193} 194 195//_____________ 196 197const BUSY = ['2019-02-12T10:00']; 198 199function optCallBackFunction (event) { 200 const 201 getParent = (n, e) => { 202 do {if (n === e.tagName) break;} while (e = e.parentNode); 203 return e; 204 }; 205 206 let 207 td = event.target; 208 inp = document.querySelector("#acdn-target"), 209 tr = this.table.querySelector('thead tr:nth-of-type(2)'), 210 d = new Date (this.current); 211 212 if ('click' === event.type) { 213 if (tr.compareDocumentPosition (td) & 16) { 214 td = getParent ('TD', td); 215 d.setDate (d.getDate () + td.cellIndex); 216 inp.value = [ 217 d.getFullYear () + '年', 218 d.getMonth () + 1 + '月', 219 d.getDate () + '日で~す' 220 ].join (''); 221 } 222 } 223} 224 225 226//_____________ 227let opt = { handleEvent: optCallBackFunction }; 228let c = new Shedule (new Date,7,BUSY, opt), {table: d} = c; 229c.setHoliday (1); 230 231document.querySelector ('#calendar').appendChild (d); 232d.addEventListener ('click', c, false); 233d.border=1; 234 235</script>

投稿2019/02/11 21:15

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

nanase21

2019/02/17 09:06

初めまして。 予約に使えるカレンダーを探していたところ、私がまさにイメージしていたカレンダーを回答していらしたので追加で1つお聞きしたいことがあるのですがよろしいでしょうか? @hai_haiさんの回答を参考にコードを編集させていただいたのですが、その過程でエラーが起きてしまいました。 私なりに考えられる原因を探り、codepenで色々試してみたのですがどうしても解決することができませんでした。 回答が既に済んでいる質問にさらに質問するのは大変ご恐縮ではございますが、教えていただくことはできないでしょうか? 下記のURLで私が、試したコードがありますのでご参照頂ける嬉しいです。 https://codepen.io/nanase21/pen/xMQNmz 私が、今していることとしては本質問者と大変似ておりますが@hai_haiさんのご教示していただいたコードを参考にランチタイム休憩時間の設定を実装しております。エラー原因としては戻り値のtable dが原因によりカレンダーを表示させることが出来ずにいます。 もしお時間に余裕があり、お分かりであればご教示頂けると嬉しいです。
退会済みユーザー

退会済みユーザー

2019/02/17 09:25

これから見ますね。ちょいとお時間を!
退会済みユーザー

退会済みユーザー

2019/02/17 12:18

let を使うときは同じスコープ内では、同じ名前の変数は使うことができません。もしよければ修正したものをアップしたいのですが、新たに質問したほうがよろしいのでは? それと、現状では年をまたいだ時におかしくなりますよ
nanase21

2019/02/17 13:04

せっかくの休日にお時間を割いてご教授頂きありがとうございます。 そうなんですね。私が学習していた教材では変数はletが使われていたため、そのような記述をしてしまいました。そのため、カレンダーが消えてしまったんですね。 分かりました。それでは新規に質問を立てますのでそちらで回答をして頂けたらと思います。
guest

0

javascript

1let 2 year = 2019, 3 start = new Date (year, 0, 1), 4 end = new Date (year, 12, 1), 5 week = 1; 6 current = new Date (start), 7 rst = [ ]; 8 9 current.setDate (7 - current.getDate () + week); 10 11 for (; current < end; current.setDate (current.getDate () + 7)) { 12 let d = new Date (current); 13 rst.push (d); 14 console.log (d, d.getDay ()); 15 } 16

投稿2019/02/11 17:22

編集2019/02/11 18:33
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

rails_ruby

2019/02/11 17:49

ご教示して頂きありがとうございます。 プログラムについては、大体理解できました。 しかし、ご教示していただいたコードを既存のコードに入れて実装する方法が分からないためもしよければ下記のリンクもしくは、質問欄にあるコードを用いた形でご教示頂くことは出来ないでしょうか? 最終的には定数BUSYにpushし、カレンダーに応用していきたいと考えているので差支えがなければよろしくお願いします。 具体的には、その曜日のtd全てを(ー)としたいと考えています。そのためにinputにtime_stratとtime_finishiがあります。それと現コードではinputに入っている日付だけはその処理が出来ます。
退会済みユーザー

退会済みユーザー

2019/02/11 18:12

プログラムをよく見てみなさい。 あなたが配列に加えなければならないのは、 this.plan です this.plan = { '09:00:00': [,,,,,,true,,,,,], //1月1日から続く通し番号順 ... }
rails_ruby

2019/02/11 18:41

申し訳ございません。大変恐縮ですが、私の今の知識レベルではthis.planを配列に加える意図がわかりません。 BUSYの配列に["2019-02-10T10:00"]のような形でデータが入るとtdがーになるのですが、this.planはtd内の○ーの判定にどのような関係があるのでしょうか?
退会済みユーザー

退会済みユーザー

2019/02/11 18:59

縦軸と横軸が反対だからすべてが面倒になっているのに起因する BUSY は人間様が理解しやすいように記述しているだけで、そのデータから直接的に表とするには非常に効率が悪い。だから内部では表に変換しやすいように予め変換して保持(this.plan)している。 つまり2月2日の9時を変えたいのなら、this.plan['09:00:00'][32] = true とする。 あとは、this.remake () を呼び出す。 この場合、this は、変数 a なので、this を a に置き換えて行う
rails_ruby

2019/02/11 20:00 編集

そうだったんですね。色々なアプローチで何とか◯ーの判定をしようと考えていましたがご教示していただいたプログラムはやっぱり私には難しすぎるようです。懇切に説明していただいたても、私にはどのようにthis.planを弄るかが理解できませんでした... ずっと、何とかBUSYまでデータを渡せば判定が変えれると思ってやっていましたがthis.planで判定を制御していたとは思っていませんでした。
退会済みユーザー

退会済みユーザー

2019/02/11 21:20

もう休みを設けるプログラムを追加したよ。 あくまでもこのスレの質問の答えではないので、間違わないように。
退会済みユーザー

退会済みユーザー

2019/02/12 04:12 編集

あのさ、このスレの質問(タイトル)だけを見て、もしかして自分の解決に繋がるかもしれない?!と思った人が このベストアンサーを見て、何これ?何の回答?って思うだろ! わざわざ忠告した意味がない。
rails_ruby

2019/02/12 04:33

申し訳ございませんでした。 忠告に気づきませんでした。 すぐにタイトル変更いたします。
退会済みユーザー

退会済みユーザー

2019/02/12 04:40

ありがとうございます。 修正前の質問で答えてくださった人の努力は、無視するのですね(w)
guest

0

ベストアンサー

前の質問からとんできました

任意の年の任意の曜日に対して指定した時間をすべて30分おきに
BUSYに流し込むという条件で

javascript

1<script> 2const BUSY = [ 3 '2019-02-12T10:00', 4 '2019-02-09T23:30' 5]; 6window.addEventListener('DOMContentLoaded', function(){ 7 document.querySelector('#btn').addEventListener('click',function(){ 8 var y=document.querySelector('#year').value; 9 var d=new Date(y+"-01-01"); 10 var w1=d.getDay(); 11 var w2=parseInt(document.querySelector('#week').value); 12 var offset=30; 13 var t1=document.querySelector('#time_start').value; 14 var t2=document.querySelector('#time_finish').value; 15 d.setDate(d.getDate()+(w2-w1+7)%7); 16 while(d.getFullYear()==y){ 17 var d0=y+"-"+("0"+(d.getMonth()+1)).substr(-2)+"-"+("0"+d.getDate()).substr(-2); 18 var d1=new Date(d0+" "+t1);d1.setTime(d1.getTime()+1000*60*60*9); 19 var d2=new Date(d0+" "+t2);d2.setTime(d2.getTime()+1000*60*60*9); 20 var m=Array((d2.getTime()-d1.getTime())/1000/60/offset+1).fill(null).map(function(x,y){ 21 return (new Date(d1.getTime()+1000*60*offset*y)).toISOString().substr(0,16); 22 }); 23 [].push.apply(BUSY,m); 24 d.setDate(d.getDate()+7); 25 } 26 console.log(BUSY); 27 }); 28}); 29</script> 30 31<input type="text" value="2019" id="year" size="4" pattern="(19|20)[0-9]{2}"> 32<select name="week" id="week"> 33<option value="0">sun</option> 34<option value="1">mon</option> 35<option value="2">tue</option> 36<option value="3">wed</option> 37<option value="4">thu</option> 38<option value="5">fri</option> 39<option value="6">sat</option> 40</select> 41<input type="time" value="08:00" id="time_start"> 42<input type="time" value="10:00" id="time_finish"> 43<input type="button" value="go" id="btn">

投稿2019/02/12 02:23

yambejp

総合スコア114825

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

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

rails_ruby

2019/02/12 02:47

ありがとうございます。 意図した処理を実現する事が出来ました。
guest

0

とりあえず 1週間おき [実行結果]
※ 最後に同じ年という条件をいれてないため 2019年が顔をだすw

固定回数毎だとこういう記述になるかと(わざわざ指定回数-1を空回しするなと)「

// your code goes here var date = new Date("2018-01-01"); print(date); var step = 7; for (var i = 0; i< 365; i+=step) { date = new Date(+date + (step * 24 * 60 * 60 * 1000)); print(date); }

投稿2019/02/11 13:56

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2019/02/11 14:29

ああ ideone の動作のでやってるから変えてないだけであって内容は window.print じゃないw
kei344

2019/02/11 14:32

そういうものが有るんですね、知りませんでした。失礼しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問