web-dev-qa-db-ja.com

SimpleDateFormatでGregorianCalendarを使用する

そのため、プログラムが日付文字列をGregorianCalendarオブジェクトに変換し、フォーマットし、完了したら再び文字列として返すようにするための、この(べきである)簡単な演習に頭を悩ませてきました。

これは、ファイルからテキストチャックを取り込み、それを個々のレコードに分割し、レコードを個々のデータに分割して、それらを人物オブジェクトに割り当てるプログラムの最後の少しです。

複数の場所でコードをチェックしましたが、コードはIllegalArgumentExceptionをスローするformat関数を呼び出すまで正確に実行します。 GergorianCalendarオブジェクトには、割り当てられるはずの値が割り当てられます(ただし、以下に示すように、これも印刷されますが…)。

残念なことに、インストラクターはGregorianCalendarSimpleDateFormatの使用方法を確信していませんでした(まだ私たちに協力してもらいました)。私が助けたことがわかりました。

私がこれまでに持っているコードは次のとおりです。

public class DateUtil {

    public static GregorianCalendar convertFromDMY(String dd_mm_yy) throws ParseException{

        // this actually works, got rid of the original code idea
        String[] splitDate = dd_mm_yy.split("-");
        int days = Integer.parseInt(splitDate[0]);
        int month = Integer.parseInt(splitDate[1]);
        int year = Integer.parseInt(splitDate[2]);

        // Dates are going in right, checked in print statement,
        // but the object is not getting formatted…
        GregorianCalendar dateConverted = new GregorianCalendar(year, month, days);
        format(dateConverted);
        return dateConverted;
    }

    public static String format(GregorianCalendar date){

        SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy");
        String dateFormatted = fmt.format(date);
        return dateFormatted;
    }
}

私が得るエラーは:

スレッド「メイン」の例外Java.lang.IllegalArgumentException:指定されたオブジェクトをJava.text.DateFormat.format(DateFormat.Java:281)の日付
 
としてフォーマットできません
 at Java.text.Format.format(Format.Java:140)
 at lab2.DateUtil.format(DateUtil.Java:26)
 at lab2.DateUtil.convertFromDMY( DateUtil.Java:19)
 at lab2.Lab2.createStudent(Lab2.Java:75)
 at lab2.Lab2.main(Lab2.Java:34)

そして、もう1つ、GregorianCalendarを使用していますか??そのオブジェクトの値を出力すると(日付を取得するはずです)、次のようになります。

Java.util.GregorianCalendar [time = ?, areFieldsSet = false、areAllFieldsSet = false、lenient = true、zone = Sun.util.calendar.ZoneInfo [id = "America/Vancouver"、offset = -28800000、dstSavings = 3600000、useDaylight = true、transitions = 189、lastRule = Java.util.SimpleTimeZone [id = America/Vancouver、offset = -28800000、dstSavings = 3600000、useDaylight = true、startYear = 0、startMode = 3、startMonth = 2、startDay = 8、 startDayOfWeek = 1、startTime = 7200000、startTimeMode = 0、endMode = 3、endMonth = 10、endDay = 1、endDayOfWeek = 1、endTime = 7200000、endTimeMode = 0]]、firstDayOfWeek = 1、minimalDaysInFirstWeek = 1、ERA = ?, YEAR = 1985、MONTH = 4、WEEK_OF_YEAR = ?, WEEK_OF_MONTH = ?, DAY_OF_MONTH = 22、DAY_OF_YEAR = ?, DAY_OF_WEEK = ?, DAY_OF_WEEK_IN_MONTH = ?, AM_PM = 0、HOUR = 0、HOUR_OF_DAY = 0、SECOND = 0、MILLISECOND = ?, ZONE_OFFSET = ?, DST_OFFSET =?]

年、月、およびday_of_monthの値は、作成に渡した数値なのですべて正しいです。

考え、提案、私も近いですか?

編集

元の問題は解決しました(ありがとうassylias!)、しかし、2つの関数がリンクされておらず、要件がGregorianCalendar日付値をpersonオブジェクトから出力する必要があるため、まだ正しく印刷できません(as生年月日はGregorianCalendar)です。

更新されたコード:

public class DateUtil {

    static SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy");

    public static GregorianCalendar convertFromDMY(String dd_mm_yy) throws ParseException{

        // this actually works, got rid of the original code idea
        String[] splitDate = dd_mm_yy.split("-");
        int days = Integer.parseInt(splitDate[0]);
        int month = (Integer.parseInt(splitDate[1]) - 1);
        int year = Integer.parseInt(splitDate[2]);

        // dates go in properly
        GregorianCalendar dateConverted = new GregorianCalendar(year, month, days);
        String finalDate = format(dateConverted);
        return ;
    }

    public static String format(GregorianCalendar date) throws ParseException{

       fmt.setCalendar(date);
        String dateFormatted = fmt.format(date.getTime());
        System.out.println(dateFormatted);
        return dateFormatted;
    }

}

最終編集

わかりましたので、私は馬鹿だと思われるので、2つのDateUtil関数をリンクする必要はありませんが、それらを一緒に使用します。まず、生年月日をGregorianCalendarに変換し、personオブジェクトに保存します。次に、printステートメントで、プログラムにその日付を印刷時にフォーマットするように指示するだけです。問題は解決しました。すべてが仕様どおりに動作するようになりました。私は、DateUtilクラスで最後の日かそこらで魚のようにひらめき、同時に動作するようにしようとしていたので、そんなにばかげていると感じました。

日付を正しく取得するためのすべての助けをありがとう!

28
RejectionHurts

SimpleDateFormat.format()メソッドは、パラメーターとしてDateを取ります。 getTime()メソッドを呼び出すことで、DateからCalendarを取得できます。

public static String format(GregorianCalendar calendar) {
    SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy");
    fmt.setCalendar(calendar);
    String dateFormatted = fmt.format(calendar.getTime());

    return dateFormatted;
}

また、月は0から始まることに注意してください。

int month = Integer.parseInt(splitDate[1]) - 1;
48
assylias

なぜそのような合併症なのか?

public static GregorianCalendar convertFromDMY(String dd_mm_yy) throws ParseException 
{
    SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy");
    Date date = fmt.parse(dd_mm_yy);
    GregorianCalendar cal = GregorianCalendar.getInstance();
    cal.setTime(date);
    return cal;
}
4
m0skit0
  1. あなたはそこに2桁の年を入れています。最初の世紀。そして、グレゴリオ暦は16世紀に始まりました。年に2000を追加する必要があると思います。

  2. 関数new GregorianCalendar(year, month, days)の月は0から始まります。そこの月から1を引きます。

  3. 2番目の関数の本体を次のように変更します。

    _    String dateFormatted = null;
        SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy");
        try {
            dateFormatted = fmt.format(date);
        }
        catch ( IllegalArgumentException e){
            System.out.println(e.getMessage());
        }
        return dateFormatted;
    _

デバッグ後、単にGregorianCalendarfmt.format();の引数にすることはできません。

本当に、「文字列」を返すように言われても、出力としてGregorianCalendarは必要ありません。

フォーマット関数のヘッダーを変更します

_public static String format(final Date date) 
_

適切な変更を行います。 fmt.format()Dateオブジェクトを喜んで受け取ります。

  1. 予期しない例外が発生した後は常に、自分でキャッチし、Javaマシンに許可しないでください。この方法で、問題を理解できます。
2
Gangnus

tl; dr

LocalDate.parse(
    "23-Mar-2017" ,
    DateTimeFormatter.ofPattern( "dd-MMM-uuuu" , Locale.US ) 
)

レガシーの日時クラスを避ける

質問とその他の回答は古くなっており、Java.timeクラスに取って代わられた、今ではレガシーである厄介な古い日時クラスを使用しています。

Java.timeを使用する

日付のみの値を扱っているようです。そのため、日時クラスを使用しないでください。代わりにLocalDateを使用してください。 LocalDate クラスは、時刻およびタイムゾーンのない日付のみの値を表します。

Locale を指定して、(a)曜日名、月名などの翻訳用の人間の言語、および(b)略語、大文字、句読点、区切り文字の問題を決定する文化的規範を決定します、 など。

文字列を解析します。

String input = "23-Mar-2017" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MMM-uuuu" , Locale.US ) ;
LocalDate ld = LocalDate.parse( input , f );

文字列を生成します。

String output = ld.format( f );

年、月、および日についてテキストではなく数字が与えられた場合は、LocalDate.ofを使用します。

LocalDate ld = LocalDate.of( 2017 , 3 , 23 );  // ( year , month 1-12 , day-of-month )

こちらをご覧ください コードはIdeOne.comでライブ実行されます

入力:2017年3月23日

ld.toString():2017-03-23

出力:2017年3月23日


Java.timeについて

Java.time フレームワークはJava 8以降に組み込まれています。これらのクラスは、面倒な古い legacy のような日時クラスに取って代わります Java.util.DateCalendar 、& SimpleDateFormat

Joda-Time プロジェクトは、現在 メンテナンスモード であり、 Java.time クラスへの移行を推奨しています。

詳細については、 Oracle Tutorial を参照してください。また、Stack Overflowで多くの例と説明を検索してください。仕様は JSR 31 です。

JDBC 4.2 以降に準拠する JDBCドライバー を使用すると、Java.timeオブジェクトをデータベースと直接交換できます。文字列もJava.sql。*クラスも必要ありません。

Java.timeクラスはどこで入手できますか?

ThreeTen-Extra プロジェクトは、Java.timeを追加のクラスで拡張します。このプロジェクトは、Java.timeに将来追加される可能性のある証明の場です。 IntervalYearWeekYearQuarter 、および more

2
Basil Bourque