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

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

ただいまの
回答率

88.64%

PostgreSQLからのデータ出力がうまくいかない

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 326

kumakura

score 6

前提・実現したいこと

勉強を始めたばかりの初心者です。
Java(jsp、サーブレット)にて`スケジュール管理のシステムを作成しています。

データベース(PostgreSQL)へ登録済みの予定が各日付部分にデータベースから出力されるように作成しています。(現時点ではカレンダー上の初日のみ作成済み)

しかし前月・来月のボタンを押し、表示している月を変更すると表示されているデータベースからの出力が一切行われません。

前月・来月のボタンを押した際に表示されている日付自体は問題なく変わるので、データベースからの出力部分がうまくいっていないのだとは思いますが、根本的な原因がわからずハマってしまっています。

ご回答いただけると助かります、よろしくお願いします。

JSPページ

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="calendar.Top" %>
<%@ page import="java.util.Calendar"%>
<%@ page import="java.sql.ResultSet" %>
<%@ page import="java.time.LocalDate" %>
<%@ page import="java.time.LocalDateTime"%>
<%@ page import="java.time.LocalTime" %>
<%@ page import="java.time.format.DateTimeFormatter" %>
<%
Calendar calendar = Calendar.getInstance();

int year;
int month;
int day;

//前月・来月に飛んだ場合
String move = request.getParameter("move");
String syear = request.getParameter("year");
String smonth = request.getParameter("month");

if(move==null){

    //現時点の日付
year = calendar.get(Calendar.YEAR);
month = calendar.get(Calendar.MONTH)+1;
day = calendar.get(Calendar.DATE);

}else{

year = Integer.parseInt(syear);
month = Integer.parseInt(smonth);
day = 1;

if(month==13) {
    year += 1;
    month = 1;
}else if(month==0) {
    year = year - 1;
    month = 12;
}else {
    year = year;
    month = month;
}
}

//今月最初の曜日
calendar.set(year,month-1,1);
int startWeek = calendar.get(Calendar.DAY_OF_WEEK);

//前月の日数
calendar.set(year,month-1,0);
int beforedaycount = calendar.get(Calendar.DATE);

//今月の日数・今月最後の曜日
calendar.set(year,month,0);
int daycount = calendar.get(Calendar.DATE);
int lastWeek = calendar.get(Calendar.DAY_OF_WEEK);

//日付用の配列作成
int [] cl = new int[42];
int count = 0;

//先月の日数を格納
for (int i = startWeek-2 ; i >= 0 ; i--){
      cl[count++] = beforedaycount - i;
    }

//今月の日数を格納
for(int i = 0;i<=daycount-1;i++) {
    cl[count++] = 1+i;
}

//来月の日数を格納
for(int i=0;i<=7-lastWeek;i++) {
    cl[count++] = 1+i;
}

//何週分を格納したか確認
int weekCount = count / 7;

//データベースへ接続
Top db = new Top();
db.open();

//データベース出力用
LocalDate daydate;
java.sql.Date sqlday;
ResultSet rs;

%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="calender.css">
<title>calender</title>
</head>
<body>
<main>
      <h1>
      <% out.println(year+"年"+month+"月"); %>
      <% int yearnow=year; %>
      <% int monthnow=month; %>
      </h1>
      <a href="new.jsp">NEW</a>
      <div class="calender">
        <div class="weeks">
          <div class="week sunday">
            <b></b>
          </div>
          <div class="week">
            <b></b>
          </div>
          <div class="week">
            <b></b>
          </div>
          <div class="week">
            <b></b>
          </div>
          <div class="week">
            <b></b>
          </div>
          <div class="week">
            <b></b>
          </div>
          <div class="week saturday">
            <b></b>
          </div>
        </div>
        <div class="days">

    //カレンダー上の初日
        <div class="day sunday">
        <% int cday = cl[0]; %>
          <p>
            <% out.println(cday); %>
            </p>
            <div class="apo">
            <%
            //年月日の算出
            year = db.prevyear(year,month,cday);
            month = db.prevmonth(year,month,cday);
            //年月日の変換、データ参照
            rs = db.getResultSet("select * from calendar where day='"+db.sql(year, month, cday)+"'");
            while (rs.next()){
                //SQL時間データをLocalへ変換
                  java.sql.Time starttimes = rs.getTime("starttime");
                  java.sql.Time lasttimes = rs.getTime("lasttime");
                //結果出力部分
                out.print(db.starttime(year,month,day,starttimes));
                out.print(db.timewhile(year,month,day,starttimes,lasttimes));
                out.print(db.lasttime(year,month,day,lasttimes));
                out.print(db.titlewhile(year,month,day,starttimes,lasttimes));
                out.println(rs.getString("title"));
                out.println("");
                %>
                <br>
                <%
                //year,monthを初期値へ戻す
                month = monthnow;
                year = yearnow;
            }%>
            </div>
            </div>

   //カレンダー上の2日目
          <div class="day">
            <p>
            <% out.println(cl[1]); %>
            </p>
            <div class="apo">
            </div>
          </div>

   -中略-

        </div>
        <% }else{
            System.out.print("");
        }%>
      </div>
      <a class="prev" href="calender.jsp?move=prev&year=<%= year %>&month=<%= monthnow-1 %>">前月</a>
      <a class="next" href="calender.jsp?move=next&year=<%= year %>&month=<%= monthnow+1 %>">来月</a>
    </main>
</body>
</html>

インポートしているオリジナルクラス

package calendar;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

public class Top {

    private String url;
    private String user;
    private String password;
    private Connection conn;
    private Statement state;
    private ResultSet rs;

    public Top() {
        url = "-省略-";
        user = "-省略-";
        password = "-省略-";
    }

    //データベースへの接続する
    public  void open() throws Exception {
        conn = DriverManager.getConnection(url, user, password);
        state = conn.createStatement();
    }

    //SQL 文を実行した結果の ResultSet を返す
    public ResultSet getResultSet(String sql) throws Exception {
        if ( state.execute(sql) ) {
            return state.getResultSet();
        }
        return null;
    }

    //データベースを閉じる
    public void close() throws Exception {
        if ( rs != null ) rs.close();
        if ( state != null ) state.close();
        if ( conn != null ) conn.close();
    }

    //年の固定(前月分日付の場合)
    public int prevyear (int year,int month,int day) {
        if(day>20 && month==1){
            return year -= 1;
        }else{
            return year;
        }
    }

  //月の固定(前月分日付の場合)
    public int prevmonth (int year,int month,int day) {
        if(day>20 && month==1){
            return month = 12;
        }else{
            return month -=1;
        }
    }

  //年の固定(来月分日付の場合)
    public int nextyear (int year,int month,int day) {
        if(day>20 && month==12){
            return year += 1;
        }else{
            return year;
        }
    }

  //月の固定(来月分日付の場合)
    public int nextmonth (int year,int month,int day) {
        if(day>20 && month==12){
            return month = 1;
        }else{
            return month +=1;
        }
    }

  //予定開始時間の出力
    public String starttime(int year,int month,int day,java.sql.Time starttimes) {

        DateTimeFormatter dtformat1 = DateTimeFormatter.ofPattern("HH:mm");

        if(starttimes==null) {
            return "";

        }else {

            //SQL時間データをLocalへ変換
              LocalTime starttimet = starttimes.toLocalTime();
              LocalDateTime starttimel = starttimet.atDate(LocalDate.of(year, month, day));

            //時間の表示方法指定
              String stime = dtformat1.format(starttimel);

             return stime;
        }
    }

//予定開始時間と終了時間間の「~」の出力
    public String timewhile(int year,int month,int day,java.sql.Time starttimes,java.sql.Time lasttimes) {
        if(starttimes==null && lasttimes==null) {
            return "";
        }else {
            return "~";
        }
    }

  //予定終了時間の出力
    public String lasttime(int year,int month,int day,java.sql.Time lasttimes) {

        DateTimeFormatter dtformat1 = DateTimeFormatter.ofPattern("HH:mm");

        if(lasttimes==null) {
            return "";
        }else {

            //SQL時間データをLocalへ変換

              LocalTime lasttimet = lasttimes.toLocalTime();
              LocalDateTime lasttime = lasttimet.atDate(LocalDate.of(year, month, day));

            //時間の表示方法指定
              String ltime = dtformat1.format(lasttime);

              return ltime;
        }
    }

  //時間と予定名間の「:」の出力
        public String titlewhile(int year,int month,int day,java.sql.Time starttimes,java.sql.Time lasttimes) {
            if(starttimes==null && lasttimes==null) {
                return "";
            }else {
                return ":";
            }
        }

   //SQLから取り出したデータ型の変換
        public java.sql.Date sql (int year,int month,int day){
            LocalDate daydate = LocalDate.of(year, month, day);
            java.sql.Date sqlday = java.sql.Date.valueOf(daydate);
            return sqlday;
        }

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • m6u

    2020/04/01 18:05

    年と月と日って別個のデータだとハンドリングが面倒なので、日付・時刻を扱うクラスに任せた方がらくなんじゃないかな、javaがよくわからないけど。指定フォーマットの文字列として出力するメソッドも必ずあるでしょうし。

    キャンセル

  • jimbe

    2020/04/01 19:48

    > -中略-
    もしや, 日毎の記述が一か月分並んでいるんですか...

    キャンセル

  • jimbe

    2020/04/01 20:22

    コードに全角スペースが入り込んでいます.
    省略は仕方ありませんが, こちらに張り付ける際に修正したものと思われます.

    キャンセル

  • jimbe

    2020/04/01 22:47

    > 前月・来月のボタンを押した際に表示されている日付自体は問題なく変わるので、データベースからの出力部分がうまくいっていないのだとは思います

    出力部分の SQL を表示して合っているかを確認するとか, 列名が合っているか確認する等をしてみては如何でしょうか.

    キャンセル

回答 2

check解決した方法

0

年・月・日を完全に別データとして扱っていましたが、一つのデータとして扱える別クラスを元に各日付のインスタンスを作成した所うまくいきました。
ご回答ありがとうございました。

package calendar;

import java.util.Calendar;

public class Cl {

    Calendar cl = Calendar.getInstance();

    int year;
    int month;
    int day;

    //いつの年月日のカレンダーか固定
    public Cl(int year,int month,int day) {

        int years = year;
        int months = month;
        int days = day;

        if(month==12) {
            year += 1;
            month = 0;
        }else if(month==-1) {
            year = year - 1;
            month = 11;
        }else {
            years = year;
            months = month;
            days = day;
        }

        this.year = years;
        this.month = months;
        this.day = days;

        cl.set(years,months,days);

    }

    //今月は何曜日から始まるか
    //前月日付をいくつ表示する必要があるか
    public int prevday() {
        if(cl.get(Calendar.DAY_OF_WEEK)==1){
            return 0;
        }else if(cl.get(Calendar.DAY_OF_WEEK)==2){
            return 1;
        }else if(cl.get(Calendar.DAY_OF_WEEK)==3) {
            return 2;
        }else if(cl.get(Calendar.DAY_OF_WEEK)==4) {
            return 3;
        }else if(cl.get(Calendar.DAY_OF_WEEK)==5) {
            return 4;
        }else if(cl.get(Calendar.DAY_OF_WEEK)==6) {
            return 5;
        }else{
            return 6;
        }

    }

    //今月の日数はいつまでか
    public int nowday() {
        int nowday = cl.getActualMaximum(Calendar.DAY_OF_MONTH);
        return nowday;
    }

    //翌月の日数はいつまでか
    public int nextday(int prevday,int nowday) {
        int day = prevday+nowday;
        if(day%7==0) {
            return 0;
        }else if((day+1)%7==0) {
            return 1;
        }else if((day+2)%7==0) {
            return 2;
        }else if((day+3)%7==0) {
            return 3;
        }else if((day+4)%7==0) {
            return 4;
        }else if((day+5)%7==0) {
            return 5;
        }else{
            return 6;
        }
    }

    //カレンダー上の初日を決定
    public void oneday(int prevday) {
        cl.add(Calendar.DAY_OF_MONTH, -prevday);
    }

    //年を返す
    public int year() {
        return cl.get(Calendar.YEAR);
    }

    //月を返す
    public int month() {
        return cl.get(Calendar.MONTH);
    }

    //日を返す
    public int day() {
        return cl.get(Calendar.DATE);
    }

    //一日後の日付を返す
    public int days() {
        cl.add(Calendar.DAY_OF_MONTH, 1);
        return cl.get(Calendar.DATE);
    }

}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/04/02 17:03 編集

    //一日後の日付を返す
    public int days() {
    cl.add(Calendar.DAY_OF_MONTH, 1);
    return cl.get(Calendar.DATE);
    }

    コメントと違い, 日を進めてしまっていますが大丈夫でしょうか.

    コンストラクタでの年月の補正個所も, 変数名が s が無かったりしています.

    キャンセル

0

回答にはならないのですが, 以下のコードをお試しになることを提案します.

String sy = "2020"; //任意
String sm = "1"; //任意
の数値を変えると, 月跨ぎ年跨ぎが確認出来ると思います.

カレンダーの課題(?)のコードを見る度に思うのですが, 皆さん前後の月の日付を扱うのに苦労されています.
が, 例えば, ある日以前の日曜日を求めるなら, Calendar から一日ずつ日を戻って日曜日を探せばよいわけで, その時に月を跨ごうが年を跨ごうが Calendar が補正してくれます.
そこから必要な分ループし Calendar を一日ずつ進めれば, 例えば(前年)前月から今月を経て(来年)来月までの日付をその都度 Calendar が示しますので, 日を保存しておく必要もありません.
その状態から「日のスケジュールを得て表示する」ようにすれば, 少なくとも日付の(計算)間違いによるデータの取得失敗は防げるかと思います.

package teratail.q250724;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;

public class Test {
  public static void main(String[] args) {
    Calendar calendar = Calendar.getInstance();

    String move = "move";
    if(move != null) {
      String sy = "2020";
      String sm = "1";
      if(sy != null && sy.matches("\\d{4}") && sm != null && sm.matches("\\d{1,2}")) {
        int y = Integer.parseInt(sy);
        int m = Integer.parseInt(sm);
        if(2000 <= y && y <= 2100 && 1 <= m && m <= 12) { //年の範囲制限はテキトウ
          calendar.set(Calendar.YEAR, y);
          calendar.set(Calendar.MONTH, m - 1);
        }
      }
    }

    calendar.add(Calendar.MONTH, -1); //前月
    int prevYear = calendar.get(Calendar.YEAR);
    int prevMonth = calendar.get(Calendar.MONTH) + 1;

    calendar.add(Calendar.MONTH, 2); //来月
    int nextYear = calendar.get(Calendar.YEAR);
    int nextMonth = calendar.get(Calendar.MONTH) + 1;

    calendar.add(Calendar.MONTH, -1); //今月
    int year = calendar.get(Calendar.YEAR);
    int month = calendar.get(Calendar.MONTH) + 1;

    //月初週の日曜日
    while(calendar.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) calendar.add(Calendar.DATE, -1);

    System.out.println("今月: "+year+"/"+month);
    do {
      //一日分の表示
      System.out.print(calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY ? "*" :
                       calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY ? "+" : " ");
      java.sql.Date sqlDate = new java.sql.Date(calendar.getTimeInMillis());
      System.out.println(sqlDate+"("+"日月火水木金土".charAt(calendar.get(Calendar.DAY_OF_WEEK)-1)+")");

      calendar.add(Calendar.DATE, 1);
    } while(calendar.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY || calendar.get(Calendar.MONTH)+1 == month);

    System.out.println("前月: "+prevYear+"/"+prevMonth);
    System.out.println("次月: "+nextYear+"/"+nextMonth);
  }
}
今月: 2020/1
*2019-12-29(日)
 2019-12-30(月)
 2019-12-31(火)
 2020-01-01(水)
 2020-01-02(木)
 2020-01-03(金)
+2020-01-04(土)
*2020-01-05(日)
 2020-01-06(月)
 2020-01-07(火)
 2020-01-08(水)
 2020-01-09(木)
 2020-01-10(金)
+2020-01-11(土)
*2020-01-12(日)
 2020-01-13(月)
 2020-01-14(火)
 2020-01-15(水)
 2020-01-16(木)
 2020-01-17(金)
+2020-01-18(土)
*2020-01-19(日)
 2020-01-20(月)
 2020-01-21(火)
 2020-01-22(水)
 2020-01-23(木)
 2020-01-24(金)
+2020-01-25(土)
*2020-01-26(日)
 2020-01-27(月)
 2020-01-28(火)
 2020-01-29(水)
 2020-01-30(木)
 2020-01-31(金)
+2020-02-01(土)
前月: 2019/12
次月: 2020/2

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 88.64%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る