Skip to content

Instantly share code, notes, and snippets.

@tokuhirom
Last active November 29, 2018 05:54
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tokuhirom/0b7441684653cb85cefa to your computer and use it in GitHub Desktop.
Save tokuhirom/0b7441684653cb85cefa to your computer and use it in GitHub Desktop.
Java 8 Date And Time API - Sample code.
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class DateTimeFormatterSample {
public static void main(String[] args) {
String[][] patterns = new String[][]{
new String[]{"G", "appendText(ChronoField.ERA,"},
new String[]{"GG", "appendText(ChronoField.ERA,"},
new String[]{"GGG", "appendText(ChronoField.ERA,"},
new String[]{"GGGG", "appendText(ChronoField.ERA,"},
new String[]{"GGGGG", "appendText(ChronoField.ERA,"},
new String[]{"", ""},
new String[]{"u", "appendValue(ChronoField.YEAR,"},
new String[]{"uu", "appendValueReduced(ChronoField.YEAR,"},
new String[]{"uuu", "appendValue(ChronoField.YEAR,"},
new String[]{"uuuu", "appendValue(ChronoField.YEAR,"},
new String[]{"y", "appendValue(ChronoField.YEAR_OF_ERA,"},
new String[]{"yy", "appendValueReduced(ChronoField.YEAR_OF_ERA,"},
new String[]{"yyy", "appendValue(ChronoField.YEAR_OF_ERA,"},
new String[]{"yyyy", "appendValue(ChronoField.YEAR_OF_ERA,"},
new String[]{"Y", "append"},
new String[]{"YY", "append"},
new String[]{"YYY", "append"},
new String[]{"YYYY", "append"},
new String[]{"", ""},
new String[]{"Q", "appendValue(IsoFields.QUARTER_OF_YEAR);"},
new String[]{"QQ", "appendValue(IsoFields.QUARTER_OF_YEAR,"},
new String[]{"QQQ", "appendText(IsoFields.QUARTER_OF_YEAR,"},
new String[]{"QQQQ", "appendText(IsoFields.QUARTER_OF_YEAR,"},
new String[]{"QQQQQ", "appendText(IsoFields.QUARTER_OF_YEAR,"},
new String[]{"q", "appendValue(IsoFields.QUARTER_OF_YEAR);"},
new String[]{"qq", "appendValue(IsoFields.QUARTER_OF_YEAR,"},
new String[]{"qqq", "appendText(IsoFields.QUARTER_OF_YEAR,"},
new String[]{"qqqq", "appendText(IsoFields.QUARTER_OF_YEAR,"},
new String[]{"qqqqq", "appendText(IsoFields.QUARTER_OF_YEAR,"},
new String[]{"", ""},
new String[]{"M", "appendValue(ChronoField.MONTH_OF_YEAR);"},
new String[]{"MM", "appendValue(ChronoField.MONTH_OF_YEAR,"},
new String[]{"MMM", "appendText(ChronoField.MONTH_OF_YEAR,"},
new String[]{"MMMM", "appendText(ChronoField.MONTH_OF_YEAR,"},
new String[]{"MMMMM", "appendText(ChronoField.MONTH_OF_YEAR,"},
new String[]{"L", "appendValue(ChronoField.MONTH_OF_YEAR);"},
new String[]{"LL", "appendValue(ChronoField.MONTH_OF_YEAR,"},
new String[]{"LLL", "appendText(ChronoField.MONTH_OF_YEAR,"},
new String[]{"LLLL", "appendText(ChronoField.MONTH_OF_YEAR,"},
new String[]{"LLLLL", "appendText(ChronoField.MONTH_OF_YEAR,"},
new String[]{"", ""},
new String[]{"w", "append"},
new String[]{"ww", "append"},
new String[]{"W", "append"},
new String[]{"d", "appendValue(ChronoField.DAY_OF_MONTH)"},
new String[]{"dd", "appendValue(ChronoField.DAY_OF_MONTH,"},
new String[]{"D", "appendValue(ChronoField.DAY_OF_YEAR)"},
new String[]{"DD", "appendValue(ChronoField.DAY_OF_YEAR,"},
new String[]{"DDD", "appendValue(ChronoField.DAY_OF_YEAR,"},
new String[]{"F", "appendValue(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH)"},
new String[]{"E", "appendText(ChronoField.DAY_OF_WEEK,"},
new String[]{"EE", "appendText(ChronoField.DAY_OF_WEEK,"},
new String[]{"EEE", "appendText(ChronoField.DAY_OF_WEEK,"},
new String[]{"EEEE", "appendText(ChronoField.DAY_OF_WEEK,"},
new String[]{"EEEEE", "appendText(ChronoField.DAY_OF_WEEK,"},
new String[]{"e", "append"},
new String[]{"ee", "append"},
new String[]{"eee", "appendText(ChronoField.DAY_OF_WEEK,"},
new String[]{"eeee", "appendText(ChronoField.DAY_OF_WEEK,"},
new String[]{"eeeee", "appendText(ChronoField.DAY_OF_WEEK,"},
new String[]{"c", "append"},
new String[]{"ccc", "appendText(ChronoField.DAY_OF_WEEK,"},
new String[]{"cccc", "appendText(ChronoField.DAY_OF_WEEK,"},
new String[]{"ccccc", "appendText(ChronoField.DAY_OF_WEEK,"},
new String[]{"a", "appendText(ChronoField.AMPM_OF_DAY,"},
new String[]{"h", "appendValue(ChronoField.CLOCK_HOUR_OF_AMPM)"},
new String[]{"hh", "appendValue(ChronoField.CLOCK_HOUR_OF_AMPM,"},
new String[]{"H", "appendValue(ChronoField.HOUR_OF_DAY)"},
new String[]{"HH", "appendValue(ChronoField.HOUR_OF_DAY,"},
new String[]{"k", "appendValue(ChronoField.CLOCK_HOUR_OF_DAY)"},
new String[]{"kk", "appendValue(ChronoField.CLOCK_HOUR_OF_DAY,"},
new String[]{"K", "appendValue(ChronoField.HOUR_OF_AMPM)"},
new String[]{"KK", "appendValue(ChronoField.HOUR_OF_AMPM,"},
new String[]{"m", "appendValue(ChronoField.MINUTE_OF_HOUR)"},
new String[]{"mm", "appendValue(ChronoField.MINUTE_OF_HOUR,"},
new String[]{"s", "appendValue(ChronoField.SECOND_OF_MINUTE)"},
new String[]{"ss", "appendValue(ChronoField.SECOND_OF_MINUTE,"},
new String[]{"", ""},
new String[]{"SSSS", "appendFraction(ChronoField.NANO_OF_SECOND,"},
new String[]{"A", "appendValue(ChronoField.MILLI_OF_DAY)"},
new String[]{"AAAA", "appendValue(ChronoField.MILLI_OF_DAY,"},
new String[]{"n", "appendValue(ChronoField.NANO_OF_SECOND)"},
new String[]{"nnnn", "appendValue(ChronoField.NANO_OF_SECOND,"},
new String[]{"N", "appendValue(ChronoField.NANO_OF_DAY)"},
new String[]{"NNNN", "appendValue(ChronoField.NANO_OF_DAY,"},
new String[]{"VV", "appendZoneId()"},
new String[]{"z", "appendZoneText(TextStyle.SHORT)"},
new String[]{"zz", "appendZoneText(TextStyle.SHORT)"},
new String[]{"zzz", "appendZoneText(TextStyle.SHORT)"},
new String[]{"zzzz", "appendZoneText(TextStyle.FULL)"},
new String[]{"O", "appendLocalizedOffsetPrefixed(TextStyle.SHORT);"},
new String[]{"OOOO", "appendLocalizedOffsetPrefixed(TextStyle.FULL);"},
new String[]{"X", "appendOffset(\"+HHmm\",\"Z\")"},
new String[]{"XX", "appendOffset(\"+HHMM\",\"Z\")"},
new String[]{"XXX", "appendOffset(\"+HH:MM\",\"Z\")"},
new String[]{"XXXX", "appendOffset(\"+HHMMss\",\"Z\")"},
new String[]{"XXXXX", "appendOffset(\"+HH:MM:ss\",\"Z\")"},
new String[]{"x", "appendOffset(\"+HHmm\",\"+00\")"},
new String[]{"xx", "appendOffset(\"+HHMM\",\"+0000\")"},
new String[]{"xxx", "appendOffset(\"+HH:MM\",\"+00:00\")"},
new String[]{"xxxx", "appendOffset(\"+HHMMss\",\"+0000\")"},
new String[]{"xxxxx", "appendOffset(\"+HH:MM:ss\",\"+00:00\")"},
new String[]{"Z", "appendOffset(\"+HHMM\",\"+0000\")"},
new String[]{"ZZ", "appendOffset(\"+HHMM\",\"+0000\")"},
new String[]{"ZZZ", "appendOffset(\"+HHMM\",\"+0000\")"},
new String[]{"ZZZZ", "appendLocalizedOffset(TextStyle.FULL);"},
new String[]{"ZZZZZ", "appendOffset(\"+HH:MM:ss\",\"Z\")"}
};
ZonedDateTime zonedDateTime = LocalDateTime
.parse("2015-07-13T12:27:04")
.atZone(ZoneId.of("Asia/Tokyo"));
System.out.printf("%-7s : %-19s\t%-19s // %s\n", "Pattern", "English", "Japanese", "Comment");
for (String[] pattern : patterns) {
try {
DateTimeFormatter enFormatter = DateTimeFormatter.ofPattern(pattern[0], Locale.ENGLISH);
String en = zonedDateTime.format(enFormatter);
DateTimeFormatter jpFormatter = DateTimeFormatter.ofPattern(pattern[0], Locale.JAPAN);
String jp = zonedDateTime.format(jpFormatter);
System.out.printf("%-7s : %-19s\t%-19s // %s\n", pattern[0], en, jp, pattern[1]);
} catch (java.time.DateTimeException e) {
System.err.printf("cannot format '%s': %s\n", pattern[0], e.getMessage());
}
}
}
}
Pattern : English Japanese // Comment
G : AD 西暦 // appendText(ChronoField.ERA,
GG : AD 西暦 // appendText(ChronoField.ERA,
GGG : AD 西暦 // appendText(ChronoField.ERA,
GGGG : Anno Domini 西暦 // appendText(ChronoField.ERA,
GGGGG : A A // appendText(ChronoField.ERA,
: //
u : 2015 2015 // appendValue(ChronoField.YEAR,
uu : 15 15 // appendValueReduced(ChronoField.YEAR,
uuu : 2015 2015 // appendValue(ChronoField.YEAR,
uuuu : 2015 2015 // appendValue(ChronoField.YEAR,
y : 2015 2015 // appendValue(ChronoField.YEAR_OF_ERA,
yy : 15 15 // appendValueReduced(ChronoField.YEAR_OF_ERA,
yyy : 2015 2015 // appendValue(ChronoField.YEAR_OF_ERA,
yyyy : 2015 2015 // appendValue(ChronoField.YEAR_OF_ERA,
Y : 2015 2015 // append
YY : 15 15 // append
YYY : 2015 2015 // append
YYYY : 2015 2015 // append
: //
Q : 3 3 // appendValue(IsoFields.QUARTER_OF_YEAR);
QQ : 03 03 // appendValue(IsoFields.QUARTER_OF_YEAR,
QQQ : Q3 Q3 // appendText(IsoFields.QUARTER_OF_YEAR,
QQQQ : 3rd quarter 第3四半期 // appendText(IsoFields.QUARTER_OF_YEAR,
QQQQQ : 3 3 // appendText(IsoFields.QUARTER_OF_YEAR,
q : 3 3 // appendValue(IsoFields.QUARTER_OF_YEAR);
qq : 03 03 // appendValue(IsoFields.QUARTER_OF_YEAR,
qqq : 3 3 // appendText(IsoFields.QUARTER_OF_YEAR,
qqqq : 3 3 // appendText(IsoFields.QUARTER_OF_YEAR,
qqqqq : 3 3 // appendText(IsoFields.QUARTER_OF_YEAR,
: //
M : 7 7 // appendValue(ChronoField.MONTH_OF_YEAR);
MM : 07 07 // appendValue(ChronoField.MONTH_OF_YEAR,
MMM : Jul 7 // appendText(ChronoField.MONTH_OF_YEAR,
MMMM : July 7月 // appendText(ChronoField.MONTH_OF_YEAR,
MMMMM : J J // appendText(ChronoField.MONTH_OF_YEAR,
L : 7 7 // appendValue(ChronoField.MONTH_OF_YEAR);
LL : 07 07 // appendValue(ChronoField.MONTH_OF_YEAR,
LLL : 7 7 // appendText(ChronoField.MONTH_OF_YEAR,
LLLL : 7 7 // appendText(ChronoField.MONTH_OF_YEAR,
LLLLL : 7 7 // appendText(ChronoField.MONTH_OF_YEAR,
: //
w : 29 29 // append
cannot format 'DD': Field DayOfYear cannot be printed as the value 194 exceeds the maximum print width of 2
ww : 29 29 // append
W : 3 3 // append
d : 13 13 // appendValue(ChronoField.DAY_OF_MONTH)
dd : 13 13 // appendValue(ChronoField.DAY_OF_MONTH,
D : 194 194 // appendValue(ChronoField.DAY_OF_YEAR)
DDD : 194 194 // appendValue(ChronoField.DAY_OF_YEAR,
F : 6 6 // appendValue(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH)
E : Mon 月 // appendText(ChronoField.DAY_OF_WEEK,
EE : Mon 月 // appendText(ChronoField.DAY_OF_WEEK,
EEE : Mon 月 // appendText(ChronoField.DAY_OF_WEEK,
EEEE : Monday 月曜日 // appendText(ChronoField.DAY_OF_WEEK,
EEEEE : M 月 // appendText(ChronoField.DAY_OF_WEEK,
e : 2 2 // append
ee : 02 02 // append
eee : Mon 月 // appendText(ChronoField.DAY_OF_WEEK,
eeee : Monday 月曜日 // appendText(ChronoField.DAY_OF_WEEK,
eeeee : M 月 // appendText(ChronoField.DAY_OF_WEEK,
c : 2 2 // append
ccc : Mon 月 // appendText(ChronoField.DAY_OF_WEEK,
cannot format 'AAAA': Field MilliOfDay cannot be printed as the value 44824000 exceeds the maximum print width of 4
cccc : Monday 月曜日 // appendText(ChronoField.DAY_OF_WEEK,
ccccc : 1 1 // appendText(ChronoField.DAY_OF_WEEK,
a : PM 午後 // appendText(ChronoField.AMPM_OF_DAY,
cannot format 'NNNN': Field NanoOfDay cannot be printed as the value 44824000000000 exceeds the maximum print width of 4
h : 12 12 // appendValue(ChronoField.CLOCK_HOUR_OF_AMPM)
hh : 12 12 // appendValue(ChronoField.CLOCK_HOUR_OF_AMPM,
H : 12 12 // appendValue(ChronoField.HOUR_OF_DAY)
HH : 12 12 // appendValue(ChronoField.HOUR_OF_DAY,
k : 12 12 // appendValue(ChronoField.CLOCK_HOUR_OF_DAY)
kk : 12 12 // appendValue(ChronoField.CLOCK_HOUR_OF_DAY,
K : 0 0 // appendValue(ChronoField.HOUR_OF_AMPM)
KK : 00 00 // appendValue(ChronoField.HOUR_OF_AMPM,
m : 27 27 // appendValue(ChronoField.MINUTE_OF_HOUR)
mm : 27 27 // appendValue(ChronoField.MINUTE_OF_HOUR,
s : 4 4 // appendValue(ChronoField.SECOND_OF_MINUTE)
ss : 04 04 // appendValue(ChronoField.SECOND_OF_MINUTE,
: //
SSSS : 0000 0000 // appendFraction(ChronoField.NANO_OF_SECOND,
A : 44824000 44824000 // appendValue(ChronoField.MILLI_OF_DAY)
n : 0 0 // appendValue(ChronoField.NANO_OF_SECOND)
nnnn : 0000 0000 // appendValue(ChronoField.NANO_OF_SECOND,
N : 44824000000000 44824000000000 // appendValue(ChronoField.NANO_OF_DAY)
VV : Asia/Tokyo Asia/Tokyo // appendZoneId()
z : JST JST // appendZoneText(TextStyle.SHORT)
zz : JST JST // appendZoneText(TextStyle.SHORT)
zzz : JST JST // appendZoneText(TextStyle.SHORT)
zzzz : Japan Standard Time 日本標準時 // appendZoneText(TextStyle.FULL)
O : GMT+9 GMT+9 // appendLocalizedOffsetPrefixed(TextStyle.SHORT);
OOOO : GMT+09:00 GMT+09:00 // appendLocalizedOffsetPrefixed(TextStyle.FULL);
X : +09 +09 // appendOffset("+HHmm","Z")
XX : +0900 +0900 // appendOffset("+HHMM","Z")
XXX : +09:00 +09:00 // appendOffset("+HH:MM","Z")
XXXX : +0900 +0900 // appendOffset("+HHMMss","Z")
XXXXX : +09:00 +09:00 // appendOffset("+HH:MM:ss","Z")
x : +09 +09 // appendOffset("+HHmm","+00")
xx : +0900 +0900 // appendOffset("+HHMM","+0000")
xxx : +09:00 +09:00 // appendOffset("+HH:MM","+00:00")
xxxx : +0900 +0900 // appendOffset("+HHMMss","+0000")
xxxxx : +09:00 +09:00 // appendOffset("+HH:MM:ss","+00:00")
Z : +0900 +0900 // appendOffset("+HHMM","+0000")
ZZ : +0900 +0900 // appendOffset("+HHMM","+0000")
ZZZ : +0900 +0900 // appendOffset("+HHMM","+0000")
ZZZZ : GMT+09:00 GMT+09:00 // appendLocalizedOffset(TextStyle.FULL);
ZZZZZ : +09:00 +09:00 // appendOffset("+HH:MM:ss","Z")
BUILD SUCCESSFUL (total time: 0 seconds)
import java.time.Clock;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.chrono.ChronoLocalDate;
import java.time.chrono.ChronoLocalDateTime;
import java.time.chrono.Chronology;
import java.time.chrono.JapaneseChronology;
import java.time.chrono.JapaneseEra;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Locale;
import org.junit.Test;
/**
* 基本的には ZonedDateTime と LocalDate をつかっとけば問題ないです。
*
* LocalDateTime と ZonedDateTime の違いは、ZonedDateTime の方がタイムゾーン情報をもっているということにあります。
* つまり、サマータイムを考慮した計算をしてくれます。
*
* LocalDateTime: Perl の localtime() の結果に相当。タイムゾーン情報はもたない。
* ZonedDateTime: Perl の DateTime に相当。タイムゾーン情報を持つ。
*
* どちらを利用するかによって、考慮する必要がある。
* <ul>
* <li>サマータイムを考慮する必要があれば、ZonedDateTime を利用する必要がある。</li>
* </ul>
*
* @author tokuhirom
*
*/
public class DateTimeTest {
// --------------------------------------------------------------------------------
// 型の使い分け
// --------------------------------------------------------------------------------
/**
* ローカルタイムゾーンでの日時を返す。
* オブジェクトはタイムゾーン情報を持たない。
* Perl で言うところの {@code Time::Piece::localtime()} に相当。
*/
@Test
public void localDateTime() {
System.out.println(LocalDateTime.now());
// => 2014-11-25T19:13:00.966
}
/**
* 任意のタイムゾーンでの日時を返す。
* <p>
* オブジェクトはタイムゾーン情報を持つ。
* <p>
* Perl で言うところの {@code DateTime->new(time_zone => 'local')} に相当。
* <p>
* サマータイムを考慮して計算を行いたい場合にはこちらを利用する必要がある。使い分けを考えるのも面倒なので、とにかくこっちを使う、と考えておくのが良いと思う。
*/
@Test
public void zonedDateTime() {
System.out.println(ZonedDateTime.now());
// => 2014-11-25T19:17:35.242+09:00[Asia/Tokyo]
}
// --------------------------------------------------------------------------------
// 基本
// --------------------------------------------------------------------------------
@Test
public void 現在日時のインスタンスを作る() {
ZonedDateTime now = ZonedDateTime.now();
System.out.println(now.toString());
// => 2014-11-24T14:36:45.844+09:00[Asia/Tokyo]
}
@Test
public void 任意の日時のインスタンス作成() {
int year = 2006;
int month = 6;
int dayOfMonth = 2;
int hour = 16;
int minute = 30;
int second = 50;
int nanoOfSecond = 0;
ZoneId zone = Clock.systemDefaultZone().getZone();
ZonedDateTime t = ZonedDateTime.of(year, month, dayOfMonth, hour,
minute, second,
nanoOfSecond, zone);
System.out.println(t.toString());
// => 2006-06-02T16:30:50+09:00[Asia/Tokyo]
}
@Test
public void 文字列に変換する() {
ZonedDateTime t = ZonedDateTime.of(2006, 6, 2, 16,
30, 50,
0, Clock.systemDefaultZone().getZone());
// YYYY-MM-DD in local time zone.
System.out.println(t.format(DateTimeFormatter.ISO_LOCAL_DATE));
// => 2006-06-02
// HH:MM:SS in local time zone.
System.out.println(t.format(DateTimeFormatter.ISO_LOCAL_TIME));
// => 16:30:50
// YYYY-mm-ddTHH:MM:SS in local time zone.
System.out.println(t.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
// => 2006-06-02T16:30:50
}
/**
* strftime します。
*/
@Test
public void 任意のフォーマットに整形された文字列を作る() {
ZonedDateTime t = ZonedDateTime.of(2006, 6, 2, 16,
30, 50,
0, Clock.systemDefaultZone().getZone());
// フォーマット文字列はこんなかんじです:
// https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#patterns
System.out.println(t.format(DateTimeFormatter
.ofPattern("yyyy/MM/dd HH:mm:ss")));
// => 2006/06/02 16:30:50
System.out.println(t.format(DateTimeFormatter
.ofPattern("yyyy年MM月dd日 HH時mm分ss秒")));
// => 2006年06月02日 16時30分50秒
}
@Test
public void 月の日数を調べる() {
ZonedDateTime t = ZonedDateTime.of(2005, 2, 1,
0, 0, 0, 0,
Clock.systemDefaultZone().getZone());
System.out.println(t.toLocalDate().lengthOfMonth());
// => 28
}
@Test
public void 曜日を調べる() {
ZonedDateTime t = ZonedDateTime.of(2006, 6, 2, 16,
30, 50,
0, Clock.systemDefaultZone().getZone());
// 1から7の数字で、1が月曜
System.out.println(t.getDayOfWeek().getValue());
// => 5
System.out.println(t.getDayOfWeek().name());
// => FRIDAY
}
@Test
public void epoch秒からZonedDateTimeを作る() {
long epochSecond = 1416911794;
ZonedDateTime t = ZonedDateTime.ofInstant(
Instant.ofEpochSecond(epochSecond),
ZoneId.systemDefault());
System.out.println(t);
// => 2014-11-25T19:36:34+09:00[Asia/Tokyo]
}
@Test
public void ZonedDateTimeからepoch秒を作る() {
long epochSecond = 1416911794;
ZonedDateTime t = ZonedDateTime.ofInstant(
Instant.ofEpochSecond(epochSecond),
ZoneId.systemDefault());
System.out.println(t.toEpochSecond());
// => 1416911794
}
// --------------------------------------------------------------------------------
// 日時の加算・減算
// --------------------------------------------------------------------------------
@Test
public void _4日足す_4日後() {
LocalDate dt = LocalDate.of(2006, 5, 30);
System.out.println(dt.plusDays(4).format(
DateTimeFormatter.ISO_LOCAL_DATE));
// => 2006-06-03
}
@Test
public void _3年引く_3年前() {
LocalDate dt = LocalDate.of(2003, 5, 30);
System.out.println(dt.minusYears(3).format(
DateTimeFormatter.ISO_LOCAL_DATE));
// 2006-05-30
}
@Test
public void うるう年も考慮したい場合は年や月を日数で計算すべし() {
LocalDate dt = LocalDate.of(2005, 1, 10);
System.out.println(dt.minusDays(365).format(
DateTimeFormatter.ISO_LOCAL_DATE));
// 2004-01-11
}
// --------------------------------------------------------------------------------
// 2つの日時の差分を調べる
// --------------------------------------------------------------------------------
/**
* Period オブジェクトが作成されます。
*/
@Test
public void 普通に引き算() {
LocalDate dt1 = LocalDate.of(2006, 10, 5);
LocalDate dt2 = LocalDate.of(2005, 12, 1);
Period period = dt2.until(dt1);
System.out.println(period.getMonths());
// => 10
System.out.println(period.getDays());
// => 4
}
/**
* Period から 10ヶ月と4日 という差分結果を、308日 というような日数に変換することはできません。
* 最初から、日数単位の差分を取得する必要があります。
*/
@Test
public void 差分日数が知りたい() {
LocalDate dt1 = LocalDate.of(2006, 10, 5);
LocalDate dt2 = LocalDate.of(2005, 12, 1);
System.out.println(dt2.until(dt1, ChronoUnit.DAYS));
}
/**
* 翌月の処理は注意が必要だ。
* <p>
* plusMonths は単に年月に加算した後、invalid な日付になった日付から日を引いていって、正しい日付になったものを返す。
* <p>
* 具体的には、2007-03-31 に plusMonths(1) した場合、不正な値 2007-04-31 が得られる。
* 結果として、最後の正しい日付である 2007-04-30 が返却される。
* <p>
* {@link LocalDate#plusMonths(long)} の挙動は、DateTime の end_of_month で言うところの limit とおなじである。
*
* {@link http://d.hatena.ne.jp/sugyan/20140131/1391177666}
*/
@Test
public void 翌月が何月か調べる() {
LocalDate dt1 = LocalDate.of(2004, 2, 28);
System.out.println(dt1.plusMonths(1));
// => 2004-03-28
}
@Test
public void 月末が何日か調べる() {
ZonedDateTime t = ZonedDateTime.parse("2006年06月02日 16時30分50秒+0900",
DateTimeFormatter
.ofPattern("yyyy年MM月dd日 HH時mm分ss秒x"));
LocalDate d = YearMonth.from(t).atEndOfMonth();
System.out.println(d);
// => 2006-06-30
}
// --------------------------------------------------------------------------------
// 年月オブジェクト
// --------------------------------------------------------------------------------
/*
* {@code uuuu-MM} つまり {@code %Y-%m} 形式から YearMonth オブジェクトを作成できます。
*/
@Test
public void 文字列から年月オブジェクトを得る() {
YearMonth ym = YearMonth.parse("2006-01");
System.out.println(ym);
// => 2006-01
}
@Test
public void 数字から年月オブジェクトを得る() {
YearMonth ym = YearMonth.of(2006, 1);
System.out.println(ym);
// => 2006-01
}
/**
* 素朴にその月の日を舐めるとこうなります。
*/
@Test
public void その年月の日を順番になめたい() {
YearMonth ym = YearMonth.parse("2006-01");
LocalDate d = ym.atDay(1);
LocalDate endDay = ym.atEndOfMonth();
while (d.compareTo(endDay) <= 0) {
System.out.println(d);
d = d.plusDays(1);
}
// => 2006-01-01...2006-01-31
}
/**
* 素朴にその月の日を舐める方法その2である。
* <p>
* もっとちゃんとしたリストを得られるはずだと思う。。
*/
@Test
public void その年月の日を順番になめたい2() {
YearMonth ym = YearMonth.parse("2006-02");
for (int i = 1; i <= 31; ++i) {
if (!ym.isValidDay(i)) {
break;
}
LocalDate d = ym.atDay(i);
System.out.println(d);
}
// => 2006-02-01...2006-02-28
}
// --------------------------------------------------------------------------------
// 日時っぽい文字列を DateTime オブジェクトに変換する
// --------------------------------------------------------------------------------
/**
* 文字列パターンを指定した上で変換。いわゆる strptime 的なことです。
*
* @see https://docs.oracle.com/javase/jp/8/api/java/time/format/DateTimeFormatter.html#patterns
*/
@Test
public void 文字列パターンを指定した上で変換() {
ZonedDateTime t = ZonedDateTime.parse("2006年06月02日 16時30分50秒+0900",
DateTimeFormatter
.ofPattern("yyyy年MM月dd日 HH時mm分ss秒x"));
System.out.println(t);
// => 2006年06月02日 16時30分50秒
}
/**
* RFC 1123 な文字列も標準サポート。
* ただ、HTTP/1.1 では asctime 形式などもサポートする必要があるので、HTTP::Date ほど信用はできない。
* RFC 2616 3.3.1 Full Date を見るべし。
*/
@Test
public void HTTPで使われているフォーマットを変換_RFC1123() {
ZonedDateTime t = ZonedDateTime.parse("09 Feb 1994 22:23:32 GMT",
DateTimeFormatter.RFC_1123_DATE_TIME);
System.out.println(t);
}
// --------------------------------------------------------------------------------
// 様々なフォーマットの文字列に変換する
// --------------------------------------------------------------------------------
@Test
public void MySQLの日付型カラム用() {
ZonedDateTime t = ZonedDateTime.of(2006, 6, 2, 16,
30, 50,
0, Clock.systemDefaultZone().getZone());
System.out.println(t.format(DateTimeFormatter
.ofPattern("yyyy-MM-dd HH:mm:ss")));
// => 2006-06-02 16:30:50
}
/**
* メールヘッダには RFC 1123 形式で入れれば良い
* ただし、基本的にほとんどの場合はメール送信ライブラリを利用するので、気にする必要はない。
* 検索用キーワード: RFC 2822/RFC 822
*/
@Test
public void メールヘッダー用() {
ZonedDateTime t = ZonedDateTime.of(2006, 6, 2, 16,
30, 50,
0, Clock.systemDefaultZone().getZone());
System.out.println(t.format(DateTimeFormatter.RFC_1123_DATE_TIME));
// => Fri, 2 Jun 2006 16:30:50 +0900
}
/**
* HTTP Protocol 用にフォーマットするにも RFC_1123_DATE_TIME でよい。
*
* HTTP/1.1 によれば以下のようになっている。
* <pre>
* 3.3.1 Full Date
*
* HTTP applications have historically allowed three different formats
* for the representation of date/time stamps:
*
* Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
* Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
* Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
* </pre>
*/
@Test
public void HTTP_Protocol用() {
ZonedDateTime t = ZonedDateTime.of(2006, 6, 2, 16,
30, 50,
0, Clock.systemDefaultZone().getZone());
System.out.println(t.format(DateTimeFormatter.RFC_1123_DATE_TIME));
// => Fri, 2 Jun 2006 16:30:50 +0900
}
/**
* 和暦に変換します。
* <S>漢字ではでてこない。そこは文字列置換すれば良いと思います。</S>
* http://blog.ik.am/#/entries/330 ← 感じ使いたければこう。
* {@link JapaneseEra} を見れば分かる通り、明治6年より前はサポートされてないことに注意。
*/
@Test
public void 和暦年号() {
ZonedDateTime t = ZonedDateTime.of(2006, 6, 2, 16,
30, 50,
0, Clock.systemDefaultZone().getZone());
Chronology jpChrono = JapaneseChronology.INSTANCE;
ChronoLocalDate date = jpChrono.date(t);
System.out.println(date);
// => Japanese Heisei 18-06-02
ChronoLocalDateTime<? extends ChronoLocalDate> localDateTime = jpChrono
.localDateTime(t);
System.out.println(localDateTime);
// => Japanese Heisei 18-06-02T16:30:50
}
@Test
public void 和暦年号を日本語で() {
ZonedDateTime t = ZonedDateTime.of(2006, 6, 2, 16,
30, 50,
0, Clock.systemDefaultZone().getZone());
Chronology jpChrono = JapaneseChronology.INSTANCE;
ChronoLocalDateTime<? extends ChronoLocalDate> localDateTime = jpChrono
.localDateTime(t);
System.out.println(localDateTime);
// => Japanese Heisei 18-06-02
}
// --------------------------------------------------------------------------------
// タイムゾーンの概念
// --------------------------------------------------------------------------------
/**
* now メソッドの結果は、JVM のタイムゾーン設定に依存します。
*
* {@link System#currentTimeMillis} と {@link java.util.TimeZone#getDefault()} から算出されます。
* {@link java.util.TimeZone#getDefault()} の値は、{@code user.timezone} の設定で変更できます。
* つまり JVM オプションなどで変更可能です。
*/
@Test
public void JVMのタイムゾーン設定に従う() {
ZonedDateTime t1 = ZonedDateTime.now();
System.out.println(t1);
// => 2014-11-25T09:58:16.659+09:00[Asia/Tokyo]
}
@Test
public void 現在のタイムゾーン名を取得() {
ZonedDateTime t1 = ZonedDateTime.now();
System.out.println(t1.getZone().getId());
// => Asia/Tokyo
System.out.println(ZoneId.systemDefault().getId());
// => Asia/Tokyo
}
/**
* {@link java.time.ZonedDateTime#withZoneSameInstant(ZoneId)} と{@link java.time.ZonedDateTime#withZoneSameLocal(ZoneId)}
* があるが、前者しか基本的には使わない。
*/
@Test
public void タイムゾーンを変更する() {
ZonedDateTime tokyo = ZonedDateTime
.parse("2014-01-01T19:30:58+09:00[Asia/Tokyo]");
System.out.println(tokyo);
// => 2014-01-01T19:30:58+09:00[Asia/Tokyo]
// その日時の、違う場所での時刻表現を得る。
ZonedDateTime chicagoSameInstant = tokyo.withZoneSameInstant(ZoneId
.of("America/Chicago"));
System.out.println(chicagoSameInstant);
// => 2014-01-01T04:30:58-06:00[America/Chicago]
// こっちは基本使いドコロがないように思います。。
ZonedDateTime chicagoSameLocal = tokyo.withZoneSameLocal(ZoneId
.of("America/Chicago"));
System.out.println(chicagoSameLocal);
// => 2014-01-01T19:30:58-06:00[America/Chicago]
}
/**
* 会員登録フォームなどでタイムゾーン情報を入力させたい場合にはこれを利用する。
* アプリの場合にはアプリから遅らせるので最近はこれを利用しなくてはいけないシーンは減っている。
*/
@Test
public void 指定可能なタイムゾーンのリストを得る() {
System.out.println(ZoneId.getAvailableZoneIds());
// => [Asia/Aden, America/Cuiaba, Etc/GMT+9, Etc/GMT+8, ...]
}
// --------------------------------------------------------------------------------
// ロケールの概念
// --------------------------------------------------------------------------------
@Test
public void デフォルトはEnglish() {
DateTimeFormatter pattern = DateTimeFormatter
.ofPattern("yyyy年MM月dd日(EEE) HH時mm分ss秒x");
ZonedDateTime t = ZonedDateTime.of(2006, 6, 2, 16,
30, 50,
0, Clock.systemDefaultZone().getZone());
System.out.println(t.format(pattern));
// => 2006年06月02日(Fri) 16時30分50秒+09
}
/**
* DateTimeFormatter には Locale を指定することができます。
*/
@Test
public void strftimeを日本語で出す() {
DateTimeFormatter pattern = DateTimeFormatter
.ofPattern("yyyy年MM月dd日(EEE) HH時mm分ss秒x", Locale.JAPANESE);
ZonedDateTime t = ZonedDateTime.of(2006, 6, 2, 16,
30, 50,
0, Clock.systemDefaultZone().getZone());
System.out.println(t.format(pattern));
// => 2006年06月02日(金) 16時30分50秒+09
}
@Test
public void zonedDateTimeを日付から生成する() {
final ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(Instant.ofEpochSecond(1433394864), ZoneId.of("Asia/Tokyo"));
System.out.println(zonedDateTime);
// => 2015-06-04T14:14:24+09:00[Asia/Tokyo]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment