Chromium版EdgeでIEモードを使う際の注意点
Chromium版EdgeのIEモードを使用して、IE専用のイントラのWebアプリケーションを表示していると、人によって、もしくは端末によって、表示や動きに違いがありました。あるWebアプリケーションのページを表示する際、ある人のEdgeではIE11で描画されるのに対して、私のEdgeではIE7として描画されました。調べてみると、人/端末によって、互換表示するIEバージョンが異なっているようです。この動作の差異について調べてみました。
前提
本記事は、Windows10/11において、Chromium版Edgeを使用していることを前提としています。
ポイント
Chromium版EdgeのIEモードにおいて、ページ描画時に使用するIEのバージョンには、Edgeの「IEモード」とIE11の「互換表示設定」が関連する。
Edgeの「IEモード」
Edgeの「IEモード」を有効にする方法はいくつかあります。
- 一つは、Edgeのメニューから「設定など」>「Internet Explorerモードで再読み込みする」を実行する方法です。
- 別の方法としては、Edgeのメニューから「設定など」>「設定」を開き、「既定のブラウザー」で、「Internet Explorer の互換性」に設定を行う方法があります。
- また、エンタープライズサイトリストマネージャーで、対象サイトを登録する方法もあります。
Edgeの「IEモード」を有効にすると、ページの描画には、IE11のエンジンが使われます。IE11のエンジンでは、基本的にはIE11として動作しますが、IE11の「互換表示設定」が有効な場合は、IEの11~5を自動判定して動作することがあります。
エンタープライズサイトリストマネージャーでは、「互換モード」として、「既定のモード」やIE11~5を選択できます。
ちなみに、IEモードで開発者ツールを使うには、IEChooser.exeを使うことができます。実行パスはC:\Windows\System32\F12\IEChooser.exe
です。
IE11の「互換表示設定」
IE11の「互換表示設定」が有効な場合、IEの設定やWebページの内容によって、IE11, IE7, IE5あたりを自動判定して動作することがあります。ただし、詳細な条件は煩雑そうで詳しくは調べていないです。
IE11の「互換表示設定」を参照/変更するためには、IEを起動する必要がありますが、私の環境ではスタートメニューなどにIEが表示されませんでした。その場合は、コマンドプロンプトや「ファイル名を指定して実行」から次のコマンドを実行することで、IEを起動して設定することができます。この起動方法は、下記参考サイトに載っていました。
rem IEを起動するコマンド rem 「bing」部分は変更可能だが、何かしら記述する必要がある。 iexplore bing -embedding
上記では上手くIE起動できないこともありました。その場合は、PowerShellで次のコマンドを実行してIE起動できました。
$objIE = new-object -com InternetExplorer.Application $objIE.visible=$true
以上のように、Edgeの「IEモード」とIE11の「互換表示設定」は、ページの描画に大きな影響を与えることが分かりました。正しく設定することで、Webアプリケーションをスムーズに表示することができます。しかし、設定が間違っている場合は、表示や動作に不具合が生じる可能性があります。
参考サイト
電子工作初心者が ラズパイで サーボモータ1~4個を動かした方法
私は、電子工作初心者ですが、Raspberry Pi から、サーボモータ4つを動かすことができるようになったので、その時の手順をまとめてみます。
- はじめに
- サーボモータ1個を動かす(ラズパイ電源)
- サーボモータ1個を動かす(外部電源)
- サーボモータ2個を動かす
- サーボモータ3個を動かす
- サーボモータ4個を動かす
- トラブル対応
- おわりに
- 参考サイト
はじめに
サーボモータ1個であれば、いろいろなブログを参考にして、その通りに動かすことができました。 サーボモータを2個以上動かすときは電源の確保が必要で、何が必要なのか、どんな物を購入する必要があるのか悩んでしまい、なかなか進まなかったのですが、手元にあるUSB充電器や、スマホ用モバイルバッテリーが使えることが分かり解決しました。
使用したプログラミング言語はPythonです。PythonからGPIO制御するライブラリがいくつかあり、どれを使ったらよいのか迷いましたが、いくつか使ってみて、pigpioに落ち着きました。
前提条件/動作環境
- ラズパイ:Raspberry Pi 3 B+
- OS:Raspbian
- プログラミング言語:Python 3.7
- Pythonライブラリ:pigpio
- サーボモータ:マイクロサーボSG90
- 電源:家庭用コンセント接続のUSB充電器、スマホ用モバイルバッテリー
要約/ポイント
サーボモータ1個であれば、ラズパイからサーボモータへ電気を供給して、動かすことが可能。
サーボモータ2個以上の場合、ラズパイから供給できる電流が足りなくなるので、外部電源が必要。 マイクロサーボSG90は、電圧4.8~5Vで動作する。必要な電流は、いくつかのブログを見ると、だいたい、通常130~200mA、最大500mAとか1.2Aの模様。 今回、USB充電器やスマホ用モバイルバッテリーのUSBポートを使用した。USBの規格では電圧5Vに決められている。電流は、今回使ったバッテリーだと、1Aと2.1Aの2つの口があった。 今回試していないが、通常単3電池(1.5V)を3個使用し1.5V×3個=4.5V、充電式単3電池(1.2V)を4個使用し1.2V×4個=4.8Vでも良さそう。
サーボモータを動かすためには、PWMという制御信号を送る必要があり、そのための仕組みがラズパイやPythonライブラリに用意されている。
サーボモータ1個を動かす(ラズパイ電源)
pigpioインストール
PythonからラズパイのGPIOを制御するため、pigpioというライブラリを使いました。 次のコマンドでインストールできました。
$ pip install pigpio
インストールしたpigpioを使うためには、事前に常駐させておく必要があるので、次のコマンドを実行しておきました。
$ sudo pigpiod
動作確認
ラズパイで用意されているハードウェアPWMを使用するため、GPIO13を使用しました。ハードウェアPWMについては、次のブログを参考にしました。
Raspberry PiのハードウェアPWMをpigpioで出力する - Qiita
・ラズパイではハードウェアPWMに対応しているピンが4つあり、独立に制御できるのは2組ずつです。
・PWM Channel 0 : GPIO12、GPIO18
・PWM Channel 1 : GPIO13、GPIO19
プログラムは、こんな感じです。上手く動きました。
import pigpio import time SERVO_PIN = 13 pi = pigpio.pi() try: while True: pi.hardware_PWM(SERVO_PIN, 50, int(1000000*1.45/20)) time.sleep(3) pi.hardware_PWM(SERVO_PIN, 50, int(1000000*2.4/20)) time.sleep(3) pi.hardware_PWM(SERVO_PIN, 50, int(1000000*0.5/20)) time.sleep(3) except KeyboardInterrupt: pass pi.hardware_PWM(SERVO_PIN, 50, 0) pi.stop()
サーボモータ1個を動かす(外部電源)
サーボモータ2個を動かすためには、外部電源が必要になるので、外部電源を使う練習をしてみました。 外部電源としてUSB充電器を使っています。USBの仕様が次のように決められているので、サーボモータを動かすのにちょうどよいと考えました。
ユニバーサル・シリアル・バス - Wikipedia
・USB2.0 電圧5V、電流500mA
・USB3.x 電圧5V、電流900mA
プログラムは、ラズパイ電源で動かした時と同じです。上手く動かすことができました。
上記では、ハードウェアPWMを使いましたが、ソフトウェアPWMでも動かしてみました。 次のプログラムで、動かすことができましたが、高周波が少し不安定になってしまった気もしました。
import pigpio import time SERVO_PIN = 13 pi = pigpio.pi() try: while True: pi.set_servo_pulsewidth(SERVO_PIN, 1450) time.sleep(3) pi.set_servo_pulsewidth(SERVO_PIN, 2400) time.sleep(3) pi.set_servo_pulsewidth(SERVO_PIN, 500) time.sleep(3) except KeyboardInterrupt: pass pi.set_servo_pulsewidth(SERVO_PIN, 0) pi.stop()
サーボモータ2個を動かす
ハードウェアPWMを使うため、GPIO12,13に接続しました。 プログラムは次です。サーボモータ1個のときと同じ処理を、2つのサーボモータに対して行っています。 少し不安定ですが、動かすことができました。
import pigpio import time SERVO_PIN_1 = 13 SERVO_PIN_2 = 12 pi = pigpio.pi() try: while True: pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*1.45/20)) time.sleep(1) pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*1.45/20)) time.sleep(1) pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*2.4/20)) time.sleep(1) pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*2.4/20)) time.sleep(1) pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*0.5/20)) time.sleep(1) pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*0.5/20)) time.sleep(1) except KeyboardInterrupt: pass pi.hardware_PWM(SERVO_PIN_1, 50, 0) pi.hardware_PWM(SERVO_PIN_2, 50, 0) pi.stop()
サーボモータ3個を動かす
サーボモータ3個を動かそうとすると、また電源の壁がありました。 今回使ったUSB充電器では、電流が1Aまでで、サーボモータ3個を動かすのは無理でした。 なので、USB充電器でサーボモータ2個を動かし、ラズパイ電源でサーボモータ1個を動かしました。 あと、USB充電器よりもスマホ用モバイルバッテリーの方が扱いが楽だったので、モバイルバッテリーを使っています。
サーボモータ制御用のGPIOピンですが、GPIO 13,12をハードウェアPWMで使用、GPIO 17をソフトウェアPWMで使用しています。
プログラムを次のようにしました。サーボモータが増えたので、処理が長くなりましたが、やっていることは今までとあまり変わりませんでした。
import pigpio import time SERVO_PIN_1 = 13 SERVO_PIN_2 = 12 SERVO_PIN_3 = 17 pi = pigpio.pi() try: while True: pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*1.45/20)) time.sleep(1) pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*1.45/20)) time.sleep(1) pi.set_servo_pulsewidth(SERVO_PIN_3, 1450) time.sleep(1) pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*2.4/20)) time.sleep(1) pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*2.4/20)) time.sleep(1) pi.set_servo_pulsewidth(SERVO_PIN_3, 2400) time.sleep(1) pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*0.5/20)) time.sleep(1) pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*0.5/20)) time.sleep(1) pi.set_servo_pulsewidth(SERVO_PIN_3, 500) time.sleep(1) except KeyboardInterrupt: pass pi.hardware_PWM(SERVO_PIN_1, 50, 0) pi.hardware_PWM(SERVO_PIN_2, 50, 0) pi.set_servo_pulsewidth(SERVO_PIN_3, 0) pi.stop()
サーボモータ4個を動かす
サーボモータ4個を動かそうとすると、またまた電源の壁がありました。 モバイルバッテリーだとサーボモータ2個まで、ラズパイ電源だと1個までなので、最大3個までしか動かせられません。 でも、モバイルバッテリーを見ると、USBポートが2つあったので、各ポートでサーボモータ2個を動かし、計4個動かすことにしました。結果、上手く動きました。
サーボモータ制御用のGPIOピンですが、GPIO 13,12をハードウェアPWMで使用、GPIO 27,23をソフトウェアPWMで使用しています。
プログラムを次のようにしました。これも、サーボモータの増加に伴い処理が増えただけで、やっていることは同じです。
import pigpio import time SERVO_PIN_1 = 13 SERVO_PIN_2 = 12 SERVO_PIN_3 = 27 SERVO_PIN_4 = 23 pi = pigpio.pi() try: while True: pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*1.45/20)) time.sleep(1) pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*1.45/20)) time.sleep(1) pi.set_servo_pulsewidth(SERVO_PIN_3, 1450) time.sleep(1) pi.set_servo_pulsewidth(SERVO_PIN_4, 1450) time.sleep(1) pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*2.4/20)) time.sleep(1) pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*2.4/20)) time.sleep(1) pi.set_servo_pulsewidth(SERVO_PIN_3, 2400) time.sleep(1) pi.set_servo_pulsewidth(SERVO_PIN_4, 2400) time.sleep(1) pi.hardware_PWM(SERVO_PIN_1, 50, int(1000000*0.5/20)) time.sleep(1) pi.hardware_PWM(SERVO_PIN_2, 50, int(1000000*0.5/20)) time.sleep(1) pi.set_servo_pulsewidth(SERVO_PIN_3, 500) time.sleep(1) pi.set_servo_pulsewidth(SERVO_PIN_4, 500) time.sleep(1) except KeyboardInterrupt: pass pi.hardware_PWM(SERVO_PIN_1, 50, 0) pi.hardware_PWM(SERVO_PIN_2, 50, 0) pi.set_servo_pulsewidth(SERVO_PIN_3, 0) pi.set_servo_pulsewidth(SERVO_PIN_4, 0) pi.stop()
トラブル対応
作業中、躓いたところを書いておきます。
pigpioインストールエラー
Pythonライブラリのpigpioをインストールしようとして、試行錯誤、次のようなコマンドを実行していました。
$ pip install pygpio
そして、Pythonの対話形式モードから使おうとすると次のエラーが発生しました。
In [1]: import pygpio --------------------------------------------------------------------------- ModuleNotFoundError Traceback (most recent call last) <ipython-input-1-462f3c478519> in <module> ----> 1 import pygpio ~/.pyenv/versions/3.7.3/lib/python3.7/site-packages/pygpio/__init__.py in <module> 1 from __future__ import absolute_import 2 ----> 3 from Adafruit_GPIO.GPIO import * ModuleNotFoundError: No module named 'Adafruit_GPIO'
原因は、ライブラリ名のスペルミスで、誤「pygpio」、正「pigpio」でした。
pigpioインポートエラー
上手くインストールできた後、Pythonからpigpioをインポートしようとすると、次のエラーが発生することがありました。
Can't connect to pigpio at localhost(8888) Did you start the pigpio daemon? E.g. sudo pigpiod Did you specify the correct Pi host/port in the environment variables PIGPIO_ADDR/PIGPIO_PORT? E.g. export PIGPIO_ADDR=soft, export PIGPIO_PORT=8888 Did you specify the correct Pi host/port in the pigpio.pi() function? E.g. pigpio.pi('soft', 8888)
これは、事前にpigpiodを起動していないからでした。次のコマンドを実行してから、インポートすると解決です。
$ sudo pigpiod
おわりに
今回、Raspberry Pi から、サーボモータを1個、2個、3個、4個と増やして動かしてみました。電子工作の経験がなく、電源管理に悩まされましたが、動かすことができました。ものが動くと達成感がありますね。
サーボモータ4個を動かした際、4つ足のロボットを作れるかも、と無邪気に素人考えをしてしまいました。 ためしに作成して、何となく歩行した気がするので、動画も作成してみました。良かったらご覧ください。
参考サイト
- ラズパイのGPIOピンの配置を確認しました。
マイクロサーボ9g SG-90: パーツ一般 秋月電子通商-電子部品・ネット通販
- マイクロサーボSG90の主な仕様が書かれていて助かりました。
Raspberry Piでサーボモーター動作 Raspberry PiのハードウェアPWMをpigpioで出力する - Qiita
- サーボモータを制御するのに参考にさせていただきました。
- USBの電源供給仕様を確認しました。
見た目もスッキリ! ウインドウの配置・サイズを変更する方法
ブラウザを操作していてキャプチャをとるとき、どうせならウインドウサイズを揃えて、きれいにキャプチャしたくなります。 マウス操作で、いい感じに変更してもよいのですが、少し手間です。
そんなときのため、PowerShellでサクッと解決する方法を調べてみました。
ポイント
- ウインドウサイズの変更は、user32.dll の
bool MoveWindow()
でできる。ただし、呼び出すためにお作法が必要。 - ウインドウの一覧は、
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 }
動作確認環境
- Windows 10
- PowerShell 5.1
参考にさせていただいたサイト
エクスプローラーが散らかってしまう? PowerShellで整理できました!
私がWindows環境で作業をしていると、いつの間にか色々なアプリケーションのウインドウが表示されています。 目的のウインドウに切り替えようとすると、ウインドウをかきわけるのに、何度もマウス操作しなければなりません。タスクバーの操作でも、何回かクリックが必要です。 特に、10個ぐらい開いてしまっているエクスプローラーの操作が大変です。
そこで、PowerShellを使って、これらのエクスプローラーをきれいに並べることで、扱いやすくしてみました。
ポイント
$shell=New-Object -ComObject Shell.Application; $shell.Windows()
でエクスプローラーの情報を取得できました。$shell.Windows() | foreach { $_.Left=0; $_.Top=0; $_.Width=800; $_.Height=600; }
でエクスプローラーの位置とサイズを変更できました。[System.Windows.Forms.Screen]::PrimaryScreen
や[System.Windows.Forms.Screen]::AllScreens
で画面サイズを取得できました。
結果イメージ
次のように、エクスプローラーを並べてみました。
スクリプト
画面の左上から右下へ、少しずらしながら重ねて並べる。 なお、重ねる順番は、表示しているパス順にしました。
$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; }
動作確認環境
- Windows 10
- PowerShell 5.1
参考にさせていただいたサイト
ロックしないでファイル読み込み
少し特殊ですが、ファイルをロックしないで読み込みしたくなりました。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秒のスリープ)などを入れると便利です。当プログラムを実行して、スリープ中に、他のプログラムから読み書き、削除ができることを確認できるはずです。なお、他のプログラムがファイル削除した場合、削除処理成功しますが、ファイルはまだ残っていて、当プログラムがファイルクローズ後に、ファイルが削除されました。
動作確認環境
- Windows10
- Powershell 5.1
参考
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日付処理メモ(Hishidama's Java Date Memo) http://www.ne.jp/asahi/hishidama/home/tech/java/date.html
- 日時に関する情報を取得する(get) - Calendarクラス http://www.javadrive.jp/start/calendar/index2.html
- Java日付時刻APIメモ(Hishidama's Java8 Date and Time API Memo) http://www.ne.jp/asahi/hishidama/home/tech/java/datetime.html
- Java日付時刻フォーマッターメモ(Hishidama's Java8 DateTimeFormatter Memo) http://www.ne.jp/asahi/hishidama/home/tech/java/DateTimeFormatter.html