「なでしこv1」開発掲示板

なでしこv1のバグや要望を書き込む掲示板
[一覧へ] > (@955) [中] [解決]
@955■ (#2989) 旧暦変換がおかしすぎる(六曜も) - 雪乃☆雫 (2021-06-03 09:23) /中 未処理
【症状】どのような症状、現象か?
 マニュアルにも完全に正しいものは得られないことが明言されているのでアレですが、2033年問題を待つまでもなく全体的にかなりおかしいです。
 具体的には、閏月がある年において、閏月の後、高確率に存在しない日付が発生します。

【再現方法】
#-----------------------------------------------
開始日=「2023/06/15」
10回
 開始日を旧暦変換して、「{開始日},{それ}」を表示。
 開始日は開始日に「+0/0/1」を日付加算。
#-----------------------------------------------
 「2023/06/18」は「2023/05/01」で合っていますが、なんとその後「2023/06/19,2023/04/31」、「2023/06/20,2023/04/32」、「2023/06/21,2023/04/33」と、あり得ない日付(旧暦の日付は29日か30日しかありません。5月の後に4月が出る自体アレですが)が発生し、「2023/06/22」で「2023/05/05」に戻ります。
 こういった件が、ざっと確認しただけでも2021~2050までの間だけで10回あります(日数ではなく年数)

【要望】どのような解決が望ましいか?
 直ると良いですね。

【バージョン】確認したバージョン
 1.581ですが、バージョンの新旧は関係なさそう。

【その他】
 朔の日付自体は合っているように思いましたので、閏を設定する過程でナニか起きているのだと思います。
 ちなみに2021~2050で閏のある年は11回で、無事に済んでいるのは一回だけとゆうことになりますが、その無事に済んでる年が2033年というのも面白いw
 六曜取得も、内部的にはこの旧暦変換を使っていると思うので、旧暦日付の狂っている日は六曜も違ってしまいますね。
 マニュアルに2009年9月の20-23日が間違っている旨が記載されていますが、これもこの問題に起因しているので、現在に至るまで数年おきに発生していたハズです。

(#2990) とりあえずこんな無理矢理系でなんとかできそうかなあ(ついでに2033年問題も) - 雪乃☆雫 (2021-06-03 14:47) /中 未処理
※少なくとも2000-2099は修正出来ていると思う。

●旧暦変換改(西暦を)
 旧暦=西暦を旧暦変換。
 旧暦を「/」で区切る。年=それ[0]。月=それ[1]。日=それ[2]。
 #なでしこの旧暦変換の間違いを無理矢理修正。
 //朔日は正しいっぽい。その翌日辺りから一定期間、前月の31日以上の日付が現れることがある。(閏月が存在する年限定)
 もし、日>30ならば、
  日=1。仮=西暦。
  もし、月の1文字左部分=「閏」ならば、月=月の「閏」を空に置換。月=月+0.5。
  必要の間
   日=日+1。
   仮=仮に「-0/0/1」を日付加算。
   仮を旧暦変換して、それを「/」で区切る。仮月=それ[1]。
   もし、仮月の1文字左部分=「閏」ならば、仮月=仮月の「閏」を空に置換。仮月=仮月+0.5。
   もし、仮月>月ならば、月=仮月。抜ける。
  もし、月の小数部分=0でなければ、月=「閏{月の整数部分}」
  「{年}/{月を2でゼロ埋め}/{日を2でゼロ埋め}」で戻る。
 #2033年問題
 //なでしこでは「1月、2月、3月、4月、5月、6月、7月、閏7月、8月、9月、10月、閏11月、12月」と未修正のまま変換される。
 //日本カレンダー暦文化振興協会の見解(https://www.rekibunkyo.or.jp/files/pdf/20150828_2033mondaikenkailight_t.pdf)に基づき、閏11月案に修正したい。
 違えば、もし、((「2033/8/25」と西暦の日数差)≧0)かつ((「2033/12/21」と西暦の日数差)≦0)ならば、
   月=月の「閏」を空に置換。
   月=月+1。「{年}/{月}/{日}」で戻る。
 違えば、旧暦で戻る。

●六曜取得改(西暦の)
  六曜=「大安,赤口,先勝,友引,先負,仏滅」を「,」で区切る。
  西暦を旧暦変換改。
  旧暦=それを「/」で区切る。
  六曜[(旧暦[1]+旧暦[2])%6]で戻る。

(#3006) 修正 - クジラ飛行机 (2021-07-11 00:07) /中 確認待ち
具体的な修正例ありがとうございます!
修正しました。
https://github.com/kujirahand/nadesiko/commit/dd37f503a50e3a358df60e7c83168e974549b17c

(#3007) 惜しい! - 雪乃☆雫 (2021-07-12 02:37) /中 確認待ち
早速の修正ありがとうございます!
しかし・・惜しい! です・・・
例に挙げた2023年は、本来5/2であるべき所が4/31になっているため、単純に-29すればなおるのですが・・・

例えば2025年は8/1の次に7/32が出て来るという現象だったため、8/1の次が8/3になってしまっております。
#-----------------------------------------------
開始日=「2025/09/21」
5回
 開始日を旧暦変換して、「{開始日},{それ}」を表示。
 開始日は開始日に「+0/0/1」を日付加算。
#-----------------------------------------------
タブンなんですが、問題の出ている月の前月が小の月なら31日から、大の月なら32日からになっているんじゃないかと今気付きました;

また、2044年の場合は、閏月の翌月に現象が発生しているため、閏が残ってしまっています。
#-----------------------------------------------
開始日=「2044/09/20」
5回
 開始日を旧暦変換して、「{開始日},{それ}」を表示。
 開始日は開始日に「+0/0/1」を日付加算。
#-----------------------------------------------
何かワタシのあれもよっぽど変なことをしていますが、よく考えたら閏月は一年に一回しかないので、修正した日付から単純に閏を消せばよさげ?

(#3008) どうせなら根本的な解決を目指したい - 雪乃☆雫 (2021-07-12 12:26) /中 確認待ち
 Delphiは分かりませんが、主にコメントを眺めて、なんでこのようなナゾ日付が発生するのかと言うことは分かりました。

 例えば、「2028/09/20」。
 これは「2028/08/02」が正解なのですが、修正前だと7/32に、現在は8/2を飛ばして8/3となってしまうやつです。
#-----------------------------------------------
開始日=「2028/09/18」
6回
 開始日を旧暦変換して、「{開始日},{それ}」を表示。
 開始日は開始日に「+0/0/1」を日付加算。
#-----------------------------------------------

 この年の秋分は9/22です。
 なので、直前の二分二至は夏至とゆうことになります。
 夏至は6/21で、これは旧暦05/29に当たります。
 これの直前の朔は、旧5/1にあたる2028/05/24となり、これをスタートに4回計算を繰り返して、5行の朔日行列を作ってるわけですよね?
 計算で作ってませんが、こうなるものと思われます。
#-----------------------------------------------
tm0=「2028/09/20」の修正ユリウス日取得。//62034
m=「5,0,61915
5,1,61945
6,0,61974
7,0,62003
8,0,62033」
#-----------------------------------------------
 目的の旧8月が最後の行になっているので、朔日行列から旧暦を求めるところでは、日付の計算はm[4][2]を見て行わなければなりませんが、どうも「Dec(j)」が、でくりめんと? j=j-1とゆうことだとすると、m[3][2]前月の7月を見て計算してることになっちゃいますよね。これだとたしかに7/32になりまする。
 秋分を過ぎた9/23から正しく戻るのも、直前の二分二至が秋分に変わり朔日行列が変化するからですよね。
 state=0になってDec(j)するべきなパターンがよく分かりませんが、とりあえず、tm0がm[4][2]より大きかった場合は、stateを2とか3とかにしてDec(j)しないようにしたら・・・なおったりしませんかねえ・・・

(#3026) むむむ - クジラ飛行机 (2022-01-01 23:28) /中 未処理
難しいですねー😭。
2022/01/01の作業で反映したかったのですが、簡単には直せず・・・今回はパスで。

詳しい 雪乃☆雫さんに、旧暦ライブラリをなでしこで作ってもらって、それを梱包するのが早いかも。。。
もしも良かったらお願いします。


(#3029) ちょっとやってみます~ - 雪乃☆雫 (2022-01-04 16:30) /中 未処理
v3でやっていたようなデータから変換する方法ならすぐ出来そうな気はします。
(と思ってちょっとやってみようとしたら、早速v1とv3の違いにやられています~;)

データを使う方法の強みは、歴史上の実際の暦と結果が合う点ですね。
しかし、データがある範囲内しか取得出来ないんですよね~(モノスゴイ未来の旧暦なんて、あまり需要は無さそげなうえ、計算でも誤差の予測が難しくなるからどのみち正確には算出できないとは思いますが)
とりあえず、それで良ければv1で動くようにしてみます!

それとは別に、計算で出す方法は、以前にv3で太陽黄経と月黄経の計算がムリすぎて挫折しましたが、なでしこの旧暦変換で朔の日付は正しく取れるので、それでなんかうまいこと出来ないかも試してみます。

(#3035) v3のサンプルありがとうございます! - クジラ飛行机 (2022-01-08 17:39) /中 未処理
さっそく、v3のサンプルありがとうございます。
後は、v1との差異になってしまうと思いますが、よろしくお願いします!!

(#3038) できたような・・・? - 雪乃☆雫 (2022-01-18 01:11) /中 未処理
 取り合えず、なでしこ1で動くようになりました!
 最初v3で作った時とは変えて、「旧暦取得」で「旧暦変換」と同じ書式の出力が得られるようになっています。
 西暦→旧暦に関しては多分・・・タブン間違いは無いものと思うのですが><
 他に、なでしこではできない和暦→西暦の変換や、紀元前の修正ユリウス日の取得、修正ユリウス日から西暦への変換が出来ます。また、おまけで、旧暦や節切での干支、九星、六曜も取得出来ます。

https://github.com/snowdrops89/Qreki_nako

(#3044) なおるかも! - 雪乃☆雫 (2022-01-30 00:46) /中 未処理
 その後また色々やってみて、おかげさまでとっても賢くなりました!
 朔を旧暦変換、中気を二十四節気取得で無理矢理取得しているのであんまり実用的ではないケド、旧暦の計算もなでしこでいちおう出来たと思います。
 それから、元のAWKのスクリプトもだうんろーどしてみました。
 それで、ひらめきまして、普通になおりそうな予感!

 問題はこの部分なんですが・・・(300行目?)
//-----------------------------------------------------------------------
// 朔日行列から旧暦を求める。
//-----------------------------------------------------------------------
  _state := 0; j := 4;
  for i := 0 to 4 do
  begin
    if(Trunc(_tm0) < Trunc(_m[i, 2]))then
    begin
      _state := 1;
      j := i;
      Break;
    end else
    if(Trunc(_tm0) = Trunc(_m[i, 2])) then
    begin
      _state := 2;
      j := i;
      Break;
    end;
  end;
  if (_state=0) or (_state=1) then
  begin
    Dec(j);
  end;
  Result.uruu  := Trunc(_m[j, 1]);
  Result.q_mon := Trunc(_m[j, 0]);
  Result.q_day := Trunc(_tm0) - Trunc(_m[j, 2]) + 1;
#-----------------------------------------------

 なでしこで書くと、こうゆうことだと思いますが・・・
#-----------------------------------------------
※mは朔日行列(要素数5)。tm0は対象日のユリウス日。
 state=0。j=4。
 iを0から4まで繰り返す
  もし、INT(tm0)<INT(m[i][2])ならば、
   state=1。j=i。抜ける。
  違えば、もし、INT(tm0)=INT(m[i][2])ならば、
   state=2。j=i。抜ける。

 もし、(state=0)または(state=1)ならば、
  j=j-1。

 閏=INT(m[j][1])
 月=INT(m[j][0])
 日=INT(tm0)-INT(m[j][2])+1。
#-----------------------------------------------

 元のAWKのスクリプトではカウンタのiを直接使っていて、もしに引っかからずに繰り返しが終了した時(state0)、タブンiが5になっているので-1しなければならなかったんだと思います。
 しかし、こちらはiをjに代入して使用していて、jの初期値を朔日行列の要素数-1である4としているので、-1してはいけません。state1の時だけ-1すればいいので、別にstateのフラグで仕分けする必要もない感じ。

 とゆうわけで、これでいけます!!!(なでしこではできました)
 前回のとりあえずな修正も、2033年問題の部分以外は不要になるハズ。
#-----------------------------------------------
※mは朔日行列(要素数5)。tm0は対象日のユリウス日。
 j=4。
 iを0から4まで繰り返す
  もし、INT(tm0)<INT(m[i][2])ならば、    // state1。対象日のユリウス日が朔日のユリウス日より前なので
   j=i-1。抜ける。             // いっこ前の月(行)を参照します。(j=i-1)
  違えば、もし、INT(tm0)=INT(m[i][2])ならば、// state2。対象日のユリウス日と朔日のユリウス日が同じ日なので
   j=i。抜ける。              // その行を参照します。(j=i)
                       // state0。該当せずに繰り返しが終了した場合は、最後の行(j=4)を参照します。
 閏=INT(m[j][1])
 月=INT(m[j][0])
 日=INT(tm0)-INT(m[j][2])+1。
#-----------------------------------------------

 Delphiさんだと・・・こう・・・ですかねえ・・・?
//-----------------------------------------------------------------------
// 朔日行列から旧暦を求める。
//-----------------------------------------------------------------------
  j := 4;
  for i := 0 to 4 do
  begin
    if(Trunc(_tm0) < Trunc(_m[i, 2]))then
    begin
      j := i-1;
      Break;
    end else
    if(Trunc(_tm0) = Trunc(_m[i, 2])) then
    begin
      j := i;
      Break;
    end;
  end;
  Result.uruu  := Trunc(_m[j, 1]);
  Result.q_mon := Trunc(_m[j, 0]);
  Result.q_day := Trunc(_tm0) - Trunc(_m[j, 2]) + 1;
#-----------------------------------------------
 うまくいったらおなぐさみ☆
 自分ではなでしこでしかお試しができないので、試してみていただけたらと思います。
 このあたりがOKならタブンだいじょぶそう。
#-----------------------------------------------
『2025/09/23』を旧暦変換して表示。#×2025/08/03→○2025/08/02
『2028/09/20』を旧暦変換して表示。#×2028/08/03→○2028/08/02
『2031/06/21』を旧暦変換して表示。#×2031/05/03→○2031/05/02
『2042/06/21』を旧暦変換して表示。#×2042/05/05→○2042/05/04
『2044/09/22』を旧暦変換して表示。#×2044/閏08/02→○2044/08/02
『2047/09/22』を旧暦変換して表示。#×2047/08/04→○2047/08/03
#-----------------------------------------------
 どうでしょう?

(#3049) おぉ!!!ありがとうございます!! - クジラ飛行机 (2022-02-08 11:14) /中 確認待ち
ありがとうございます。気付くのが遅くなってすみません<m(__)m>
無事、修正できました!
次のバージョンで更新されます!!感謝感謝です!!

(#3053) 実行ファイルを差し替え - クジラ飛行机 (2022-02-08 15:15) /中 確認待ち
とりあえず、以下、差し替えました!

Windows版 v1.586 (2022/02/08)
https://nadesi.com/top/go.php?6

(#3054) 確認しました☆ - 雪乃☆雫 (2022-02-09 01:25) /中 解決
いちおう、1873~2099で、問題のあった日付(当初のv1.581時点での調査)が全て正しく出力されるのを確認しました☆
なおりましたね~。やった~ヽ(^o^)ノ

(#2989)へ返信する:

👆お手数ですが、いたずら防止のために、「真夏」の読み方を記入してください。

編集時に使うキーを入力(省略可能)

画像ファイル(最大300KB)を添付可能