ど忘れSEの備忘録

日々集めた何かしらを残すための何か。 共有とか疑問解決とかできたらいいな。 iPhoneとかiOSとかその他スクリプトとか色々。

SimpleDateFormatにおける日付書式による年ズレ問題

Javaのプログラムで、年が想定より1年進んで設定されるっていう事象が発生した。
しかも年末のみ。
結論から言うとどうやらSimpleDateFormatで指定する日付書式が原因だった模様。
以下のようなサンプルで検証。

import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.ParseException;

public class Test{
	public static void main(String[] args) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
		Date date = sdf.parse("2018/12/31");
		String sdate  = sdf.format(date);

		SimpleDateFormat sdf1 = new SimpleDateFormat("YYYY/MM/dd");
		String sdate1 = sdf1.format(date);
		
		String updateStr = sdf.format(date);
		System.out.print("yyyy:" + sdate + "\n");
		System.out.print("YYYY:" + sdate1);
		
	}
}

実行結果
yyyy:2018/12/31
YYYY:2019/12/31

うん、1年ずれてる。
書式指定の「yyyy」と「YYYY」の違いが原因らしい。

既に前例がいくつか報告されているので引用。

【yyyy】
年(西暦)を出力


【YYYY】
ある年における「最初の木曜日を含む週が、その年の第1週である」というルールで年(西暦)を出力。

例えば 2015/1/1 は木曜日なのでその週の日は日曜日~土曜日まで全て2015年の第1週という解釈になり、 2014/12/28(日曜)~2014/12/31(水曜) の時に YYYY を使うと 2015 を返します。

引用元
日付フォーマット yyyy と YYYY の違い - 強火で進め

なんつーシステム屋泣かせの仕様…。
幸い、複数機能のうち1か所だけだったしそこまで影響が大きくない機能だったからよかった…。
しかし年末に発生したバグが今頃みつかるっていうね…。
ログの出力方法を見直す必要がありそう。

web UIコンポーネント色々

今のシステムがIgnite UI使って構築してるんだけど、勉強がてら他のコンポーネントも見てみようかってことで探してみた。
結構種類あるなぁ…比較できるように今度まとめてみよう。

JavaScriptベースのコンポーネント
・Bootstrap
・EasyUI
・Fish-UI
・Infagistics
・JQwidgets
・Kendo UI
・Onsen UI
・React
・Titon Toolkit
・Vue.js
・Webix
・Wijmo

【Chrome拡張】webページの背景を変更するアドオン その後

forgeserem.hatenablog.com

この記事で公開したアドオンの続編。
先輩に「複数の設定ができるようにしてほしい」って要望が挙がってたのでちまちま空き時間で更新。
ラジオボタンで5つまでの設定が可能に。
さらにダイアログもjQuery UIでちゃんとしたダイアログを出すように。
例えば、システム開発において「開発環境の背景はコレ、検証環境の背景はコレ、本番はコレ」みたいな使い方をするとログイン環境の認識誤りによるヒューマンエラーが少しは防止できたり。
そんな需要ないだろうけど一応置いておく。
あ、18/12/11時点ではまだストア審査中なので後日改めて周知しよう。

12/17追記
公開された。
アップデートボタン押下で更新されんのかな…。
そこの検証すんの忘れてた…w
chrome.google.com

続きを読む

【解決】続・jQueryとAjax使ってforでループしながらigComboの中身を初期化したいよっていうお話

昨日の記事の続き。
forgeserem.hatenablog.com

続きを読む

jQueryとAjax使ってforでループしながらigComboの中身を初期化したいよっていうお話

今までのソースが「success」「error」っていう古い非推奨の書き方だったのと、各コンボBOX毎にAjaxの記述があって冗長的だったので整理も兼ねて。

$("#hoge1").igCombo({
  textKey: "hogeKey1",
  valueKey: "hogeVal"
});

$("#hoge2").igCombo({
  textKey: "hogeKey2",
  valueKey: "hogeVal"
});


(中略)

// ajaxによるコンボBOX設定
// urlはコントローラのRequestMapping
// 初期値指定がある場合にも対応したかった
var requestHdr = [
  { url: $("#contextPath").val() +"/hoge/getHoge1", id: "#hoge1", defaultVal: ""},
  { url: $("#contextPath").val() +"/hoge/getHoge1", id: "#hoge2", defaultVal: "ALL"}
];
var jqXHRListHdr = [];  // 実行するAjaxを格納する配列

for (var i = 0; i < requestHdr.length; i++) {
  jqXHRListHdr.push(
      $.ajax({
        type          : "POST",
        data          : JSON.stringify(jsonData),
        url           : requestHdr[i].url,           // 配列で指定したurlを順次受け取る
        cache         : false,
        contentType   : 'application/json',
        async         : false,
        scriptCharset : 'utf-8'
      })
      .then(
        // 通信成功時のコールバック
        function(data) {
          $(requestHdr[i].id).igCombo("option", "dataSource", data);
          // 初期値が指定されている場合はその値を設定
          if (requestHdr[i].defaultVal != "") {
            $(requestHdr[i].id).igCombo("value", requestHdr[i].defaultVal);
          }
        },
        // 通信失敗時のコールバック
        function(xhr, textStatus, errorThrown) {
          var errorInfo = $.parseJSON(xhr.responseText);
          location.href($("#contextPath").val() +"/sysError/"+ errorInfo.errNo +"/"+ errorInfo.errDate +"/"+ errorInfo.errContents);
        }
      )
  );
}

// ajaxによる処理を実行
// $.when関数にてまとめてAjax通信を実施
$.when(jqXHRListHdr).done(function () {
    console.log("通信成功");
    後続処理();
}).fail(function (ex) {
    console.log("Ajax通信に失敗しました");
});

とりあえずこんな感じで上手く設定はできた。

ただ、どうせ全通信の完了を待つなら「async : false」を取ればいいやと思いコメントアウトすると初期化ができなくなった。
どうやら
 同期の場合 :.thenの中身まで実行→後続処理の実行
 非同期の場合:後続処理の実行→.thenの中身実行
って順序になるみたい。
whenの前に.thenの処理を実行できるように記述してあげる必要があるみたいだけど、とりあえず今日は時間無くなっちゃったからここまで。
明日また頑張る。

batファイルでフォルダコピーとかショートカットとかを作りたかったお話

最近職場の変更管理フローが変更され、手間が多くなってきた。
元々1つのディレクトリで諸々管理していればよかったものを、構成管理の都合上別ファイルで管理することに。

続きを読む

【IgniteUI】formの内容をserializeObjectで取得する際のメモ

先日とある改修案件の対応をした際のメモ。
Spring MVCとIgniteUIを用いて構築された画面のフォーム操作。

var formData = $("#form").serializeObject();

こんな感じでフォームの内容を取得して変数にセットしようとした際、Stringで設定したかったあるinputの内容がArrayになってしまった。
今まではStringで取れていたのに…と悩んでいたところ、どうやら無効化がうまく動いておらず重複した項目が渡ってしまったため、勝手にArrayにされてしまった模様。
jspはこんな感じ。

<form:hidden path="From" id="hidFrom" />

(中略)

<form:input path="From" class="textCss ime-disabled" id="txtFrom" />

生成された2つのinputのnameが重複していたため、serializeObjectした際に同一項目とみなされた模様。
pathの値を元に勝手にnameつけてくれるもんなの…?
なので、片方殺してあげればいいよねってことで

$("#txtFrom").attr("disabled", true);

な感じで記述したら死なない。
正確に言うと、Textbox自体は死んでるんだけど勝手に作られたhiddenのinputが生きたままになってる。
IgniteUIのinputって、実際に入力するinputの直後にhiddenのinputを生成して、そこで値持つのね…。

悩んだ結果殺し方間違ってるじゃん、と。
IgniteUIのinputはそれ用の記述でプロパティ指定してあげないといけない模様。

$("#txtFrom").igTextEditor({
	disabled : true
});

こうすることで正しく殺せてArrayにもならず想定した値が飛ぶようになりましたとさ。