2

そのため、JodaTime の年表を使用して日付を解析する際に問題があったため、IslamicChronology問題を示すために小さな例を書きました。

コードは次のとおりです。

import org.joda.time.Chronology;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.chrono.IslamicChronology;

import java.util.Date;

/**
 * Test
 */
public class Test
{
    public static void main(String[] args)
    {
        Date now = new Date();

        String format = "dd MMM yyyy";
        Chronology calendarSystem = IslamicChronology.getInstance();
        DateTimeFormatter formatter = DateTimeFormat.forPattern(format).withChronology(calendarSystem);

        String nowAsString = formatter.print(now.getTime());

        System.out.println("nowAsString = " + nowAsString);

        long parsedNowTs = formatter.parseMillis(nowAsString);

        String parsedNowTsAsString = formatter.print(parsedNowTs);
    }
}

そして出力:

nowAsString = 16 10 1430
Exception in thread "main" java.lang.IllegalArgumentException: Invalid format: "16 10 1430" is malformed at "10 1430"
    at org.joda.time.format.DateTimeFormatter.parseMillis(DateTimeFormatter.java:634)
    at test.Test.main(Test.java:40)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    ...

問題は月の名前が数値であることだと思いますが、そうですか? 誰にも何か提案がありますか?年表がグレゴリオ暦の場合、これを再現することはできません。

前もって感謝します。

4

3 に答える 3

7

誰かが興味を持っているなら...私は回避策を見つけました:

  • たとえば、パッケージorg.joda.time.DateTimeZoneIslamicChronologyWithNamesのインスタンスに委譲 する新しいクラスを作成します。IslamicChronology
  • one メソッドを変更します。assemble(Fields fields): デリゲートのメソッドを呼び出してから、fields.monthOfYear (および場合によっては dayOfWeek) を自分のサブクラスに設定しますBasicMonthOfYearDateTimeField
  • のサブクラスはBasicMonthOfYearDateTimeField、プロパティ ファイル名で月 (DayOfWeek... の場合は日) の名前を検索できます。拡張できるようにするには、サブクラスをパッケージorg.joda.time.chronoBasicMonthOfYearDateTimeFieldに含める必要があります。

Joda time はサブクラスのようなメソッドを呼び出す前に解析している日付を検証しているように見えgetAsText(int fieldValue, Locale locale)、クラスが返す月の名前を認識していないため、検証に失敗し、メソッドを呼び出さないという問題がまだあります。私の回避策は、このクラスに、日付をイスラムの月名を持つ文字列としての日付をグレゴリオ語の英語の月名を持つ文字列として変換する静的メソッドを持つことでした。したがってparseDateTime()、 を呼び出す前に静的メソッドを呼び出すと、日付文字列が検証に合格します。次に、メソッドでイスラムの月名を処理する代わりにconvertText()、サブクラス内でデフォルトのグレゴリオ暦の実装を使用します。

protected int convertText(String text, Locale locale)
{
    return GJLocaleSymbols.forLocale(locale).monthOfYearTextToValue(text);
}

それはうまくいくはずです!同じ問題を抱えている人にとって意味があることを願っています。

于 2009-10-15T12:44:42.837 に答える
5

書式テンプレートの MMM は、月の省略名を示します。数値の月インデックスは MM で示されます。

dtsazzaの回答に関するコメントを読んだ後、私は最初にあなたの実際の問題に気づきました。:)

JODA のソース コードを調べたところ、イスラム年表のサポートが壊れているようです。まず第一に、フォーマッタは月名をサポートしていないため、パターン MMM および MMMM は月番号としてフォーマットされますが、DateTimeFormat のドキュメントによると、省略された月名を MMM に使用し、完全な月名を MMMM に使用する必要があります。 .

コード例の問題の 1 つはparseMillis、フォーマッタが別の年表で構成されているにもかかわらず、常に ISO 年表を使用していることです。これは、特に直感的ではありませんが、API ドキュメントにも記載されています。

に置き換えparseMillisた場合parseDateTime、解析に年表が使用されることを期待していましたが (少なくともドキュメントにはそう記載されています)、実装が構成された年表を無視し、ここでも ISO 年表を使用しているように見えます。

于 2009-10-06T14:30:28.947 に答える
2

フォーマットを次のように指定しましたdd MMM yyyyAPIに従って、月を省略文字列形式 (この場合は "Oct") で指定する必要があることを意味します。フォーマットがdd MM yyyy.

編集:私はあなたの要点をやや逃したようです。あなたが見つけたのは、特定のフォーマッタに対して、

long input = ...; // whatever
formatter.parseMillis(formatter.print(input));

例外をスローしています。これが常に機能するという明確な保証は見当たりませんが、私は確かにそうであると期待しています.

少なくとも、これが予期された動作である場合、それが発生する可能性があることをより明確に示す必要があります。

于 2009-10-06T14:30:17.063 に答える