kurukuru-papaのブログ

主に、ソフトウェア開発に関連したメモを書き溜めたいと思います。

見た目もスッキリ! ウインドウの配置・サイズを変更する方法

ブラウザを操作していてキャプチャをとるとき、どうせならウインドウサイズを揃えて、きれいにキャプチャしたくなります。 マウス操作で、いい感じに変更してもよいのですが、少し手間です。

そんなときのため、PowerShellでサクッと解決する方法を調べてみました。

ポイント

  1. ウインドウサイズの変更は、user32.dll の bool MoveWindow() でできる。ただし、呼び出すためにお作法が必要。
  2. ウインドウの一覧は、Get-Process -Name $name | where { $_.MainWindowTitle -ne "" } で取得できる。ただし、ブラウザで複数ウインドウを表示している場合、アクティブなウインドウのみ取得可能な模様。

スクリプト

Edge, IE, Chrome, Firefox を対象に、1024x768サイズに変更するスクリプトです。 対象ブラウザやサイズ、位置は、お好みで変更してみてください。

$name = "msedge","iexplore","chrome","firefox"
$w = 1024
$h = 768
$x = 0
$y = 0
Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class Win32Api {
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
  }
"@
Get-Process -Name $name | where { $_.MainWindowTitle -ne "" } | foreach {
  [Win32Api]::MoveWindow($_.MainWindowHandle, $x, $y, $w, $h, $true) | Out-Null
}

動作確認環境

参考にさせていただいたサイト

エクスプローラーが散らかってしまう? PowerShellで整理できました!

私がWindows環境で作業をしていると、いつの間にか色々なアプリケーションのウインドウが表示されています。 目的のウインドウに切り替えようとすると、ウインドウをかきわけるのに、何度もマウス操作しなければなりません。タスクバーの操作でも、何回かクリックが必要です。 特に、10個ぐらい開いてしまっているエクスプローラーの操作が大変です。

そこで、PowerShellを使って、これらのエクスプローラーをきれいに並べることで、扱いやすくしてみました。

ポイント

  1. $shell=New-Object -ComObject Shell.Application; $shell.Windows()エクスプローラーの情報を取得できました。
  2. $shell.Windows() | foreach { $_.Left=0; $_.Top=0; $_.Width=800; $_.Height=600; }エクスプローラーの位置とサイズを変更できました。
  3. [System.Windows.Forms.Screen]::PrimaryScreen[System.Windows.Forms.Screen]::AllScreens で画面サイズを取得できました。

結果イメージ

次のように、エクスプローラーを並べてみました。

コメント 2020-07-26 203203_2.png

スクリプト

画面の左上から右下へ、少しずらしながら重ねて並べる。 なお、重ねる順番は、表示しているパス順にしました。

$w = 800
$h = 600
$x = 0
$y = 0
$dx = 30
$dy = 30
$shell = New-Object -ComObject Shell.Application
$shell.Windows() | where { $_.Name -eq "エクスプローラー" } | sort LocationURL | foreach {
  $_.Left=$x; $_.Top=$y; $_.Width=$w; $_.Height=$h; $x+=$dx; $y+=$dy;
}

同様に、画面右下を基準に並べる。

Add-Type -AssemblyName System.Windows.Forms
$sw = [System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea.Width
$sh = [System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea.Height
$w = 800
$h = 600
$x = $sw - $w
$y = $sh - $h
$dx = -30
$dy = -30
$shell = New-Object -ComObject Shell.Application
$shell.Windows() | where { $_.Name -eq "エクスプローラー" } | sort LocationURL | foreach {
  $_.Left=$x; $_.Top=$y; $_.Width=$w; $_.Height=$h; $x+=$dx; $y+=$dy;
}

動作確認環境

参考にさせていただいたサイト

ロックしないでファイル読み込み

少し特殊ですが、ファイルをロックしないで読み込みしたくなりました。PowerShellで実装してみましたので、メモしておきます。

実装方法

ファイルをロックせずに、ファイル内容を標準出力します。ポイントは、ファイルオープン時に指定するFileShareのReadWrite、Deleteです。

$inpath = 'D:\tmp\dummy.txt'
$sr = [System.IO.StreamReader]::new(
    [System.IO.FileStream]::new(
        $inpath,
        [System.IO.FileMode]::Open,
        [System.IO.FileAccess]::Read,
        # 他プログラムの読み書き、削除をロックしない
        [System.IO.FileShare]::ReadWrite + [System.IO.FileShare]::Delete))
echo $sr.ReadToEnd()
$sr.Close()

ファイルオープン部分は、次のように書くこともできますね。

$fs = [System.IO.File]::Open(
    $inpath,
    [System.IO.FileMode]::Open,
    [System.IO.FileAccess]::Read,
    [System.IO.FileShare]::ReadWrite + [System.IO.FileShare]::Delete)
$sr = [System.IO.StreamReader]::new($fs)

テキスト読み込み部分は、次のようにして、1行ごとに処理することもできますね。

while (($line = $sr.ReadLine()) -ne $null) {
    echo $line
}

ワンライナー

Windowsコマンドプロンプトから、ワンライナーで実行する場合は、次のように書けました。

powershell -Command "$sr = [System.IO.StreamReader]::new([System.IO.FileStream]::new('D:\tmp\dummy.txt', [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite + [System.IO.FileShare]::Delete)); echo $sr.ReadToEnd(); $sr.Close()"

動作確認方法

上述のファイル読み込み中に、ロックがかかっていないことを動作確認するときは、読み込み処理の途中で、Start-Sleep 10(10秒のスリープ)などを入れると便利です。当プログラムを実行して、スリープ中に、他のプログラムから読み書き、削除ができることを確認できるはずです。なお、他のプログラムがファイル削除した場合、削除処理成功しますが、ファイルはまだ残っていて、当プログラムがファイルクローズ後に、ファイルが削除されました。

動作確認環境

参考

Windows標準機能だけで文字列置換できた!

まったく予期していなかったのですが、Windows標準機能だけで、テキストファイルの文字列置換を行えるのですね。びっくりです。

次の2つのサイトが非常に参考になりました。

knowledge.reontosanta.com
blogs.yahoo.co.jp

私が書いたWindowsバッチファイル(StringConverter.bat)は、次のようになりました。

@echo off
set basedir=%~dp0
set basename=%~n0
set batname=%~n0%~x0
set datestr=%DATE:/=%
set timestrtmp=%TIME: =0%
set timestr=%timestrtmp:~0,2%%timestrtmp:~3,2%%timestrtmp:~6,2%
set timestamp=%datestr%-%timestr%

:INIT
if "%1"=="/?" (
  echo 使い方:%batname% 入力ファイル 出力ファイル 置換前文字列 置換後文字列
  exit /b 0
)
if "%4"=="" (
  echo 引数の数が不正です。
  goto ERROR
)
set inpath=%1
set outpath=%2
set before=%3
set after=%4

:MAIN
call :LOG 処理開始します。


type nul > %outpath%
setlocal enabledelayedexpansion
for /f "tokens=1* delims=: eol=" %%a in ('findstr /n "^" %inpath%') do (
  set line=%%b
  if not "!line!" == "" (
    set line=!line:%before%=%after%!
  )
  echo.!line!>> %outpath%
)
endlocal


:END
call :LOG 正常終了です。
exit /b 0

:ERROR
call :LOG 異常終了です。
exit /b 1

:LOG
echo %DATE% %TIME% %basename% %1
exit /b 0

:EOF

このWindowsバッチファイルは、次のように実行します。

StringConverter.bat 入力ファイル 出力ファイル 置換前文字列 置換後文字列

入力ファイルのサンプルです。

サンプルデータです。
ShiftJIS、CRLFで記述されています。

空白区切り:カラム1 カラム2 カラム3
カンマ区切り:カラム1,カラム2,カラム3
タブ区切り:カラム1 カラム2 カラム3

;セミコロンで始まる行

バッチ実行後の出力ファイルは、次のようになりました。

サンプルデータです。
ShiftJIS、CRLFで記述されています。

空白区切り:column1 column2 column3
カンマ区切り:column1,column2,column3
タブ区切り:column1 column2 column3

;セミコロンで始まる行

Javaで日時を扱う(Java8)

Java8では、日時を扱うクラス群が様変わりしてしまいました。これを機に、日時の扱いをまとめてみたいと思います。前回は、Java7までの日時、今回は、Java8での日時を書きました。

Java8では、Java7までのDate,Calendarの代替として、次のクラスなどが導入されましたね。

現在/指定日時の作成

Instantクラスの現在/指定日時を作成する。

// 現在日時
Instant nowInstant = Instant.now();
// long→Instant
Instant instant2 = Instant.ofEpochMilli(msec1);
// LocalDateTime→Instant
Instant instant3b = localDt1.toInstant(ZoneId.systemDefault().getRules().getOffset(Instant.EPOCH));
// ZonedDateTime→Instant
Instant instant4ca = zonedDt1.toInstant();
Instant instant4cb = Instant.from(zonedDt1);
// 文字列→Instant
Instant instant5 = Instant.parse("2007-12-03T10:15:30.00Z");

LocalDateTimeクラスの現在/指定日時を作成する。

// 現在日時
LocalDateTime nowLocalDt = LocalDateTime.now();
// 指定日時
LocalDateTime localDt2 = LocalDateTime.of(2016, 5, 2, 15, 0, 0);
// long→LocalDateTime
LocalDateTime localDt3 = LocalDateTime.ofInstant(Instant.ofEpochMilli(msec1), ZoneId.systemDefault());
// Instant→LocalDateTime
LocalDateTime localDt4 = LocalDateTime.ofInstant(instant1, ZoneId.systemDefault());
// ZonedDateTime→LocalDateTime
LocalDateTime localDt5a = zonedDt1.toLocalDateTime();
LocalDateTime localDt5b = LocalDateTime.from(zonedDt1);
// 文字列→LocalDateTime
LocalDateTime localDt6a = LocalDateTime.parse("2007-12-03T10:15:30.123");
LocalDateTime localDt6b = LocalDateTime.parse("2007/12/03 10:15:30.123",
		DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSS"));

ZonedDateTimeの現在/指定日時を作成する。

// 現在日時
ZonedDateTime nowZonedDt = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
// 指定日時
ZonedDateTime zonedDt2 = ZonedDateTime.of(2016, 5, 2, 15, 0, 0, 0, ZoneId.of("Asia/Tokyo"));
// long→ZonedDateTime
ZonedDateTime zonedDt3 = ZonedDateTime.ofInstant(Instant.ofEpochMilli(msec1), ZoneId.systemDefault());
// Instant→ZonedDateTime
ZonedDateTime zonedDt4a = instant1.atZone(ZoneId.systemDefault());
ZonedDateTime zonedDt4b = ZonedDateTime.ofInstant(instant1, ZoneId.systemDefault());
// LocalDateTime→ZonedDateTime
ZonedDateTime zonedDt5a = localDt1.atZone(ZoneId.systemDefault());
ZonedDateTime zonedDt5b = ZonedDateTime.ofLocal(localDt1, ZoneId.systemDefault(), null);
// 文字列→ZonedDateTime型
ZonedDateTime zonedDt6a = ZonedDateTime.parse("2007-12-03T10:15:30+01:00[Europe/Paris]");
ZonedDateTime zonedDt6b = ZonedDateTime.parse("2016/05/02 10:15:30 Asia/Tokyo",
		DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss VV"));
ZonedDateTime zonedDt6c = ZonedDateTime.parse("2016/05/02 10:15:30 JST",
		DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss zzz"));

文字列の現在/指定日時を作成する。

// Instant→文字列
String instantStr1 = DateTimeFormatter.ISO_INSTANT.format(instant1);
String instantStr2 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSS")
		.format(LocalDateTime.ofInstant(instant1, ZoneId.systemDefault()));
// LocalDateTime→文字列
String localStr1 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSS").format(localDt1);
// ZonedDateTime→文字列
// "xxxxx VV" - (例)"+09:00 Asia/Tokyo"
// "xxxx zzz" - (例)"+0900 JST"
String zonedStr1a = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSSxxxxx VV").format(zonedDt1);
String zonedStr1b = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSSxxxx zzz").format(zonedDt1);

日時から日付/時刻の取り出し

// Instant 日時→日付
Instant ymdInstant1 = instant1.truncatedTo(ChronoUnit.DAYS);

// LocalDateTime 日時→日付、時刻
LocalDate localDate1 = localDt1.toLocalDate();
LocalTime localTime1 = localDt1.toLocalTime();

// ZonedDateTime 日時→日付、時刻
ZonedDateTime ymdZoned1 = zonedDt1.truncatedTo(ChronoUnit.DAYS);
LocalDate localDate2 = zonedDt1.toLocalDate();
LocalTime localTime2 = zonedDt1.toLocalTime();

曜日の取得

// Instant→曜日
String instantWeek1 = DateTimeFormatter.ofPattern("E, EEEE", Locale.JAPANESE)
		.format(LocalDateTime.ofInstant(instant1, ZoneId.systemDefault()));
String instantWeek2 = LocalDateTime.ofInstant(instant1, ZoneId.systemDefault()).getDayOfWeek()
		.getDisplayName(TextStyle.FULL, Locale.JAPANESE);

// LocalDateTime→曜日
// ※"E","EEEE"は、タイムゾーンによって曜日の表記が変わる。
String localWeek1 = DateTimeFormatter.ofPattern("E, EEEE", Locale.JAPANESE).format(localDt1);
String localWeek2 = localDt1.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.JAPANESE);

// ZonedDateTime→曜日
// ※"E","EEEE"は、タイムゾーンによって曜日の表記が変わる。
String zonedWeek1 = DateTimeFormatter.ofPattern("E, EEEE", Locale.JAPANESE).format(zonedDt1);
String zonedWeek2 = zonedDt1.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.JAPANESE);

日時計

加算/減算

// LocalDateTime 1秒後、1日後、1ヶ月後
LocalDateTime localNextSec = localDt1.plusSeconds(1);
LocalDateTime localNextDay = localDt1.plusDays(1);
LocalDateTime localNextMonth = localDt1.plusMonths(1);
// ZonedDateTime 1秒後、1日後、1ヶ月後
ZonedDateTime zonedNextSec = zonedDt1.plusSeconds(1);
ZonedDateTime zonedNextDay = zonedDt1.plusDays(1);
ZonedDateTime zonedNextMonth = zonedDt1.plusMonths(1);

月初/月末を求める。

// LocalDateTime 月初、月末
LocalDateTime localMonthBeginning = localDt1.with(TemporalAdjusters.firstDayOfMonth());
LocalDateTime localMonthEnd = localDt1.with(TemporalAdjusters.lastDayOfMonth());
// ZonedDateTime 月初、月末
ZonedDateTime zonedMonthBeginning = zonedDt1.with(TemporalAdjusters.firstDayOfMonth());
ZonedDateTime zonedMonthEnd = zonedDt1.with(TemporalAdjusters.lastDayOfMonth());

差を求める。

// LocalDateTime 日時の差 ミリ秒単位、日数単位(切り捨て)
long localDiffMsec = ChronoUnit.MILLIS.between(localDt1, localNextDay);
long localDiffDays1 = ChronoUnit.DAYS.between(localDt1, localNextDay);
long localDiffDays2 = ChronoUnit.DAYS.between(localDt1.toLocalDate(), localNextDay.toLocalDate());
// LocalDateTime 日時の差 時分秒単位、年月日単位
Duration localDuration = Duration.between(localDt1, localNextDay);
Period localPeriod = Period.between(localDt1.toLocalDate(), localNextDay.toLocalDate());
// ZonedDateTime 日時の差 ミリ秒単位、日数単位(切り捨て)
long zonedDiffMsec = ChronoUnit.MILLIS.between(zonedDt1, zonedNextDay);
long zonedDiffDays1 = ChronoUnit.DAYS.between(zonedDt1, zonedNextDay);
long zonedDiffDays2 = ChronoUnit.DAYS.between(zonedDt1.toLocalDate(), zonedNextDay.toLocalDate());
// ZonedDateTime 日時の差 時分秒単位、年月日単位
Duration zonedDuration = Duration.between(zonedDt1, zonedNextDay);
Period zonedPeriod = Period.between(zonedDt1.toLocalDate(), zonedNextDay.toLocalDate());

比較する。

// LocalDateTime
boolean localAfterFlag = localNextDay.isAfter(localDt1);
// ZonedDateTime
boolean zonedAfterFlag = zonedNextDay.isAfter(zonedDt1);

参考

Javaで日時を扱う(Java7まで)

Java8では、日時を扱うクラス群が様変わりしてしまいました。これを機に、日時の扱いをまとめてみたいと思います。今回は、Java7までの日時、次回は、Java8での日時を書きたいと思います。

Java7までは、主に、Dateクラス、Calendarクラスを使いますね。Apache Commons LangのDateUtils、DateFormatUtilsも使えると便利。

Apache Commons Lang について

現在/指定日時の作成

Dateクラスの現在/指定日時を作成する。

// 現在日時
Date nowDate1 = new Date();
// 文字列→Date
DateFormat dateTimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date1 = dateTimeFormat.parse("2016/5/2 15:00:00");
// 文字列→Date(Apache Commons Lang)
// ※Java5から、書式引数を可変長引数として記述できるようになった。
Date date1b = DateUtils.parseDate("2016/5/2 15:00:00", "yyyy/MM/dd HH:mm:ss");
Date date1c = DateUtils.parseDate("2016-5-2 15:00:00", "yyyy/MM/dd HH:mm:ss", "yyyy-MM-dd HH:mm:ss");
// Calendar→Date
Date date2 = new GregorianCalendar(2016, 5 - 1, 2, 15, 0, 0).getTime();
// long→Date
Date date3 = new Date(System.currentTimeMillis());

Calendarクラスの現在/指定日時を作成する。

// 現在日時
Calendar nowCal1 = Calendar.getInstance();
// 指定日時
Calendar cal1 = new GregorianCalendar(2016, 5 - 1, 2, 15, 0, 0);
// Date→Calendar
Calendar cal2 = Calendar.getInstance();
cal2.setTime(date1);
// Date→Calendar(Apache Commons Lang)
Calendar cal2b = DateUtils.toCalendar(date1);
// long→Calendar
Calendar cal3 = Calendar.getInstance();
cal3.setTimeInMillis(System.currentTimeMillis());

long型(ミリ秒)の現在/指定日時を作成する。

// 現在日時
long nowMsec1 = System.currentTimeMillis();
// 指定日時
long msec1 = System.currentTimeMillis() - 24 * 60 * 60 * 1000;
// Date→long
long msec2 = date1.getTime();
// Calendar→long
long msec3 = cal1.getTimeInMillis();

文字列の現在/指定日時を作成する。

// Date→文字列
DateFormat timestampFormat1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
String str1 = timestampFormat1.format(date1);
// Date→文字列(Apache Commons Lang)
String str1b = DateFormatUtils.format(date1, "yyyy/MM/dd HH:mm:ss.SSS");
// Calendar→文字列
String str2 = format.format(cal1.getTime());
// long→文字列
String str3 = format.format(new Date(msec1));

日時から日付の取り出し

// Date 日時→日付(時刻ゼロ)
Calendar tmpCal1 = Calendar.getInstance();
tmpCal1.setTime(date1);
Calendar tmpCal2 = new GregorianCalendar(tmpCal1.get(Calendar.YEAR), tmpCal1.get(Calendar.MONTH),
		tmpCal1.get(Calendar.DATE));
Date ymdDate1 = tmpCal2.getTime();

// Calendar 日時→日付(時刻ゼロ)
Calendar ymdCal1 = new GregorianCalendar(cal1.get(Calendar.YEAR), cal1.get(Calendar.MONTH),
		cal1.get(Calendar.DATE));

// Date 日時→日付(時刻ゼロ)(Apache Commons Lang)
Date ymdDate2 = DateUtils.truncate(date1, Calendar.DATE);
// Calendar 日時→日付(時刻ゼロ)(Apache Commons Lang)
Calendar ymdCal2 = DateUtils.truncate(cal1, Calendar.DATE);

// 上記以外に、書式"yyyy/MM/dd"のフォーマットで文字列として取得することも可能。

日時から時刻の取り出し

// 時刻のみを取り出すことは出来ない模様。
// 必要なら、書式"HH:mm:ss"のフォーマットで文字列として取得する(?)

曜日の取得

// Dateから曜日取得
// ※ロケールによって曜日の表記が変わる。
DateFormat weekFormat1 = new SimpleDateFormat("E", Locale.JAPANESE);
DateFormat weekFormat2 = new SimpleDateFormat("EEEE", Locale.JAPANESE);
String weekStr1 = weekFormat1.format(date1);
String weekStr2 = weekFormat2.format(date1);

// Calendarから曜日取得
int weekInt1 = cal1.get(Calendar.DAY_OF_WEEK);
String[] weekNames = new String[] { "日", "月", "火", "水", "木", "金", "土" };
String weekStr3 = weekNames[weekInt1 - 1];

// Java6では、Calendar.getDisplayNameメソッドが使える。
String weekStr4 = cal1.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT, Locale.JAPANESE);
String weekStr5 = cal1.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.JAPANESE);

// Dateから曜日取得(Apache Commons Lang)
// ※ロケールによって曜日の表記が変わる。
String weekStr6 = DateFormatUtils.format(date1, "E", Locale.JAPANESE);
String weekStr7 = DateFormatUtils.format(date1, "EEEE", Locale.JAPANESE);
// Calendarから曜日取得(Apache Commons Lang)
// ※ロケールによって曜日の表記が変わる。
String weekStr8 = DateFormatUtils.format(cal1, "E", Locale.JAPANESE);
String weekStr9 = DateFormatUtils.format(cal1, "EEEE", Locale.JAPANESE);

日時計

加算/減算

// Date 1秒後、1日後
// ※Java5では、TimeUnitが使えるようになった。
Date nextSecDate = new Date(msec1 + TimeUnit.SECONDS.toMillis(1));
Date nextDayDate = new Date(msec1 + TimeUnit.DAYS.toMillis(1));

// Calendar 1秒後、1日後、1ヶ月後
Calendar nextSecCal = (Calendar) cal1.clone();
nextSecCal.add(Calendar.SECOND, 1);
Calendar nextDayCal = (Calendar) cal1.clone();
nextDayCal.add(Calendar.DATE, 1);
Calendar nextMonthCal = (Calendar) cal1.clone();
nextMonthCal.add(Calendar.MONTH, 1);

// Date 1秒後、1日後(Apache Commons Lang)
Date nextSecDate2 = DateUtils.addSeconds(date1, 1);
Date nextDayDate2 = DateUtils.addDays(date1, 1);
Date nextMonthDate2 = DateUtils.addMonths(date1, 1);

月初/月末を求める。

// Calendar 月初、月末
Calendar monthBeginning = (Calendar) cal1.clone();
monthBeginning.set(Calendar.DATE, 1);
Calendar monthEnd = (Calendar) cal1.clone();
monthEnd.set(Calendar.DATE, cal1.getActualMaximum(Calendar.DATE));

差を求める。

// Date 日時の差 ミリ秒単位、日数単位(切り捨て)
// ※日付の差がほしいときは、日時→日付のみに変換して計算する。
long dateDiffMsec = nextDayDate.getTime() - date1.getTime();
long dateDiffDays = (nextDayDate.getTime() - date1.getTime()) / TimeUnit.DAYS.toMillis(1);

// Calendar 日時の差 ミリ秒単位、日数単位(切り捨て)
// ※日付の差がほしいときは、日時→日付のみに変換して計算する。
long calDiffMsec = nextDayCal.getTimeInMillis() - cal1.getTimeInMillis();
long calDiffDays = (nextDayCal.getTimeInMillis() - cal1.getTimeInMillis()) / TimeUnit.DAYS.toMillis(1);

// Date 日付の差(Apache Commons Lang)
long dateDiffDays2 = (DateUtils.truncate(nextDayDate, Calendar.DATE).getTime()
	- DateUtils.truncate(date1, Calendar.DATE).getTime()) / TimeUnit.DAYS.toMillis(1);
// Calendar 日付の差(Apache Commons Lang)
long calDiffDays2 = (DateUtils.truncate(nextDayCal, Calendar.DATE).getTimeInMillis()
	- DateUtils.truncate(cal1, Calendar.DATE).getTimeInMillis()) / TimeUnit.DAYS.toMillis(1);

比較する。

// Dateの前後比較
boolean dateBeforeFlag = date1.before(nextDayDate);
boolean dateAfterFlag = nextDayDate.after(date1);
// Calendarの前後比較
boolean calBeforeFlag = cal1.before(nextDayCal);
boolean calAfterFlag = nextDayCal.after(cal1);

// Date 日付一致確認(Apache Commons Lang)
// ※時刻は無視して、日付のみ比較される。
boolean dateSameFlag = DateUtils.isSameDay(date1, nextSecDate);
// Calendar 日付一致確認(Apache Commons Lang)
// ※時刻は無視して、日付のみ比較される。
boolean calSameFlag = DateUtils.isSameDay(cal1, nextSecCal);

おまけ:スリープ

Java5のTimeUnitを使うと、好きな時間単位でスリープ時間を書きやすい。

TimeUnit.SECONDS.sleep(1);

参考

ラズパイでJava8を使う

自分のRaspberry Piに、Java8をインストールしたので、メモを残しておきます。特に、難しいことはありませんでした。

事前確認

現在のJavaインストール状態を確認します。Java7がインストールされていました。

$ java -version
java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) Client VM (build 24.0-b56, mixed mode)
$
$ which java
/usr/bin/java
$ ls -l /usr/bin/java
lrwxrwxrwx 1 root root 22 Jan  8  2014 /usr/bin/java -> /etc/alternatives/java
$ ls -l /etc/alternatives/java
lrwxrwxrwx 1 root root 44 Jan  8  2014 /etc/alternatives/java -> /usr/lib/jvm/jdk-7-oracle-armhf/jre/bin/java
$ ls -l /usr/lib/jvm/jdk-7-oracle-armhf/jre/bin/java
-rwxr-xr-x 1 root root 5924 Aug 27  2013 /usr/lib/jvm/jdk-7-oracle-armhf/jre/bin/java
$
$ dpkg -l | grep jdk
ii  oracle-java7-jdk                      1.7.0+update40                          armhf        Java? Platform, Standard Edition 7 Development Kit

aptでインストール可能なJavaを確認します。Java8がインストールできることを確認できました。

$ apt-cache search oracle jdk
oracle-java7-jdk - Java? Platform, Standard Edition 7 Development Kit
oracle-java8-jdk - Java? Platform, Standard Edition 8 Development Kit

OSアップデート

以降の作業を安定して進めるため、次のコマンドでOSをアップデートしました。

$ sudo apt-get update

Java8インストール

次のコマンドでインストールしました。

$ sudo apt-get install oracle-java8-jdk
$ dpkg -l | grep oracle
ii  oracle-java7-jdk                      1.7.0+update40                          armhf        Java? Platform, Standard Edition 7 Development Kit
ii  oracle-java8-jdk                      8                                       armhf        Java? Platform, Standard Edition 8 Development Kit
$ java -version
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) Client VM (build 25.0-b70, mixed mode)
$ which java
/usr/bin/java
$ ls -l /usr/bin/java
lrwxrwxrwx 1 root root 22  1月  8  2014 /usr/bin/java -> /etc/alternatives/java
$ ls -l /etc/alternatives/java
lrwxrwxrwx 1 root root 51  5月 14 21:47 /etc/alternatives/java -> /usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt/jre/bin/java
$ ls -l /usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt/jre/bin/java
-rwxr-xr-x 1 root root 5912  3月  5  2014 /usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt/jre/bin/java

設定

環境変数JAVA_HOMEを使用するアプリケーションのため、次の設定をしておきます。

$ JAVA_HOME=/usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt

もし、今回インストールする前のJava7を使いたい場合は、次の設定で使えるようになります。

$ JAVA_HOME=/usr/lib/jvm/jdk-7-oracle-armhf
$ PATH=${JAVA_HOME}/bin:${PATH}
$ java -version
java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) Client VM (build 24.0-b56, mixed mode)