LocalDateTime的探索源代码及使用

Why?

在项目开发过程中中经常遇到时间处理。一般是用了Date配合Calendar再配合SimpleDateFormat使用。但是

  1. 阿里巴巴开发手册中却禁用SimpleDateFormat.因为线程不安全。
  2. 而且Date中好多方法已经过时
  3. 方法返回的值不直观,可读性差。
  4. jdk8新出的比较先进, 更新了好多东西。

What?

LocalDate

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//获取当前年月日
LocalDate localDate = LocalDate.now();
//构造指定的年月日
LocalDate localDate1 = LocalDate.of(2020, 1, 10);
System.out.println(localDate);//2020-01-21
System.out.println(localDate1);//2020-01-10

System.out.println(localDate.get(ChronoField.YEAR));//2020
System.out.println(localDate.getDayOfMonth());//21
System.out.println(localDate.getDayOfYear());//21
System.out.println(localDate.getLong(ChronoField.DAY_OF_MONTH));//21
System.out.println(localDate.getMonthValue());//1
System.out.println(localDate.getYear());//2020
System.out.println(localDate.getChronology());//ISO
System.out.println(localDate.getDayOfWeek());//TUESDAY
System.out.println(localDate.getEra());//CE
System.out.println(localDate.getMonth());//JANUARY
System.out.println(localDate.lengthOfMonth());//31
System.out.println(localDate.lengthOfYear());//366
System.out.println(localDate.range(ChronoField.MONTH_OF_YEAR));//1 - 12
System.out.println(localDate.compareTo(localDate1));//11
System.out.println(localDate.format(DateTimeFormatter.ofPattern("YYYY--MM--dd")));//2020--01--21
System.out.println(localDate.isAfter(localDate1));//true
System.out.println(localDate.isBefore(localDate1));//false
System.out.println(localDate.isEqual(localDate1));//false

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
public final class LocalDate implements Temporal, TemporalAdjuster, ChronoLocalDate, Serializable {
//支持的最小日期:最小年的1月1日==>+999999999-12-31
public static final LocalDate MIN = LocalDate.of(Year.MIN_VALUE, 1, 1);
//支持的最大日期:最大年的12月31日==>-999999999-01-01
public static final LocalDate MAX = LocalDate.of(Year.MAX_VALUE, 12, 31);
//序列化版本UID
private static final long serialVersionUID = 2942565459149668126L;
//每400年一个大周期(平年闰年等等)等于146097天
private static final int DAYS_PER_CYCLE = 146097;
//从0年到1970年经过的天数==>5个400年大周期减去30年(其中1970-2000有7个闰年所以加上7天)
static final long DAYS_0000_TO_1970 = (DAYS_PER_CYCLE * 5L) - (30L * 365L + 7L);
//年月日用不同数据类型保存节省资源
private final int year;
private final short month;
private final short day;
//获取当地的当前时间,调用了Clock.systemDefaultZone()-->SystemClock[Asia/Shanghai]
//然后return new SystemClock(ZoneId.systemDefault());
//然后return TimeZone.getDefault().toZoneId();
//此时区的字符串标识符。这是一个编程标识符,用于在内部从系统表中查找时区对象,并将它们映射到其本地化的显示名称。ID值在系统表中是唯一的,但不能用于动态创建的区域
public static LocalDate now() {
return now(Clock.systemDefaultZone());
}
//获取指定地区的当前时间,调用了Clock.system(zone)
//然后return new SystemClock(zone);
public static LocalDate now(ZoneId zone) {
return now(Clock.system(zone));
}
//获取指定的Clock的当前时间,Clock是时钟抽象类,实现类有4个,其中SystemClock是用System.currentTimeMillis()来实现获取时间。
public static LocalDate now(Clock clock) {
Objects.requireNonNull(clock, "clock");
// clock.instant()-->Instant.ofEpochMilli(millis())-->Instant.ofEpochMilli(System.currentTimeMillis())
//其中Instant.ofEpochMilli()把精确到微妙强行精确到纳秒,存到Instant.nanoOfSecond里面
final Instant now = clock.instant(); // called once
ZoneOffset offset = clock.getZone().getRules().getOffset(now); // 根据时区获取不同地区偏移量规则来获取秒偏移量
long epochSec = now.getEpochSecond() + offset.getTotalSeconds(); // 加上去
//一天多少秒 static final int SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY;
long epochDay = Math.floorDiv(epochSec, SECONDS_PER_DAY); // 计算出当前日
return LocalDate.ofEpochDay(epochDay); // 转化为年月日返回
}
//获取指定年月日的LocalDate对象
public static LocalDate of(int year, Month month, int dayOfMonth) {
YEAR.checkValidValue(year); //return (value >= getMinimum() && value <= getMaximum());
Objects.requireNonNull(month, "month");
DAY_OF_MONTH.checkValidValue(dayOfMonth);
//检查年、日合理,且月非空后返回创建后的LocalDate, create方法有检查月合理且二月29日等错误
return create(year, month.getValue(), dayOfMonth);
}
//一样,检查年月日合理
public static LocalDate of(int year, int month, int dayOfMonth) {
YEAR.checkValidValue(year);
MONTH_OF_YEAR.checkValidValue(month);
DAY_OF_MONTH.checkValidValue(dayOfMonth);
return create(year, month, dayOfMonth);
}
//获取指定年日的LocalDate对象,月份根据日来计算
public static LocalDate ofYearDay(int year, int dayOfYear) {
YEAR.checkValidValue(year);
DAY_OF_YEAR.checkValidValue(dayOfYear);
boolean leap = IsoChronology.INSTANCE.isLeapYear(year);
if (dayOfYear == 366 && leap == false) {
throw new DateTimeException("Invalid date 'DayOfYear 366' as '" + year + "' is not a leap year");
}
Month moy = Month.of((dayOfYear - 1) / 31 + 1);
int monthEnd = moy.firstDayOfYear(leap) + moy.length(leap) - 1;
if (dayOfYear > monthEnd) {
moy = moy.plus(1);
}
int dom = dayOfYear - moy.firstDayOfYear(leap) + 1;
return new LocalDate(year, moy.getValue(), dom);
}
//获取指定日的LocalDate对象,年月根据日来计算(日期从1970年开始)
public static LocalDate ofEpochDay(long epochDay) {
long zeroDay = epochDay + DAYS_0000_TO_1970;
zeroDay -= 60;
long adjust = 0;
if (zeroDay < 0) {
long adjustCycles = (zeroDay + 1) / DAYS_PER_CYCLE - 1;
adjust = adjustCycles * 400;
zeroDay += -adjustCycles * DAYS_PER_CYCLE;
}
long yearEst = (400 * zeroDay + 591) / DAYS_PER_CYCLE;
long doyEst = zeroDay - (365 * yearEst + yearEst / 4 - yearEst / 100 + yearEst / 400);
if (doyEst < 0) {
yearEst--;
doyEst = zeroDay - (365 * yearEst + yearEst / 4 - yearEst / 100 + yearEst / 400);
}
yearEst += adjust;
int marchDoy0 = (int) doyEst;
int marchMonth0 = (marchDoy0 * 5 + 2) / 153;
int month = (marchMonth0 + 2) % 12 + 1;
int dom = marchDoy0 - (marchMonth0 * 306 + 5) / 10 + 1;
yearEst += marchMonth0 / 10;
int year = YEAR.checkValidIntValue(yearEst);
return new LocalDate(year, month, dom);
}
//获取指定时间的LocalDate对象
public static LocalDate from(TemporalAccessor temporal) {
Objects.requireNonNull(temporal, "temporal");
LocalDate date = temporal.query(TemporalQueries.localDate());
if (date == null) {
throw new DateTimeException("Unable to obtain LocalDate from TemporalAccessor: " +
temporal + " of type " + temporal.getClass().getName());
}
return date;
}
//获取指定字符串的LocalDate对象,调用了下面那个方法,默认用ISO_LOCAL_DATE
public static LocalDate parse(CharSequence text) {
return parse(text, DateTimeFormatter.ISO_LOCAL_DATE);
}
//获取指定字符串的LocalDate对象,验证DateTimeFormatter非空,然后通过formatter.parse解析。
public static LocalDate parse(CharSequence text, DateTimeFormatter formatter) {
Objects.requireNonNull(formatter, "formatter");
return formatter.parse(text, LocalDate::from);
}
//通过年月日创建的LocalDate对象
private static LocalDate create(int year, int month, int dayOfMonth) {
if (dayOfMonth > 28) {
int dom = 31;
switch (month) {
case 2:
dom = (IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28);
break;
case 4:
case 6:
case 9:
case 11:
dom = 30;
break;
}
if (dayOfMonth > dom) {
if (dayOfMonth == 29) {
throw new DateTimeException("Invalid date 'February 29' as '" + year + "' is not a leap year");
} else {
throw new DateTimeException("Invalid date '" + Month.of(month).name() + " " + dayOfMonth + "'");
}
}
}
return new LocalDate(year, month, dayOfMonth);
}
////通过年月日创建的LocalDate对象,保证日期正确
private static LocalDate resolvePreviousValid(int year, int month, int day) {
switch (month) {
case 2:
day = Math.min(day, IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28);
break;
case 4:
case 6:
case 9:
case 11:
day = Math.min(day, 30);
break;
}
return new LocalDate(year, month, day);
}
//年月日构造LocalDate
private LocalDate(int year, int month, int dayOfMonth) {
this.year = year;
this.month = (short) month;
this.day = (short) dayOfMonth;
}
//检查是否支持指定的字段,比如ChronoField.DAY_OF_WEEK
@Override // override for Javadoc
public boolean isSupported(TemporalField field) {
return ChronoLocalDate.super.isSupported(field);
}
//检查是否支持指定的字段,比如ChronoUnit.DAYS
@Override // override for Javadoc
public boolean isSupported(TemporalUnit unit) {
return ChronoLocalDate.super.isSupported(unit);
}
//获取指定时间的范围localDate.range(ChronoField.DAY_OF_WEEK)输出为1 - 7
@Override
public ValueRange range(TemporalField field) {
if (field instanceof ChronoField) {
ChronoField f = (ChronoField) field;
if (f.isDateBased()) {
switch (f) {
case DAY_OF_MONTH: return ValueRange.of(1, lengthOfMonth());
case DAY_OF_YEAR: return ValueRange.of(1, lengthOfYear());
case ALIGNED_WEEK_OF_MONTH: return ValueRange.of(1, getMonth() == Month.FEBRUARY && isLeapYear() == false ? 4 : 5);
case YEAR_OF_ERA:
return (getYear() <= 0 ? ValueRange.of(1, Year.MAX_VALUE + 1) : ValueRange.of(1, Year.MAX_VALUE));
}
return field.range();
}
throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
}
return field.rangeRefinedBy(this);
}
//获取LocalDate指定字段的信息,验证一下调get0
@Override // override for Javadoc and performance
public int get(TemporalField field) {
if (field instanceof ChronoField) {
return get0(field);
}
return ChronoLocalDate.super.get(field);
}
//获取LocalDate指定字段的信息(返回Long)
@Override
public long getLong(TemporalField field) {
if (field instanceof ChronoField) {
if (field == EPOCH_DAY) {
return toEpochDay();
}
if (field == PROLEPTIC_MONTH) {
return getProlepticMonth();
}
return get0(field);
}
return field.getFrom(this);
}
//获取LocalDate指定字段的信息
private int get0(TemporalField field) {
switch ((ChronoField) field) {
case DAY_OF_WEEK: return getDayOfWeek().getValue();
case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((day - 1) % 7) + 1;
case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((getDayOfYear() - 1) % 7) + 1;
case DAY_OF_MONTH: return day;
case DAY_OF_YEAR: return getDayOfYear();
case EPOCH_DAY: throw new UnsupportedTemporalTypeException("Invalid field 'EpochDay' for get() method, use getLong() instead");
case ALIGNED_WEEK_OF_MONTH: return ((day - 1) / 7) + 1;
case ALIGNED_WEEK_OF_YEAR: return ((getDayOfYear() - 1) / 7) + 1;
case MONTH_OF_YEAR: return month;
case PROLEPTIC_MONTH: throw new UnsupportedTemporalTypeException("Invalid field 'ProlepticMonth' for get() method, use getLong() instead");
case YEAR_OF_ERA: return (year >= 1 ? year : 1 - year);
case YEAR: return year;
case ERA: return (year >= 1 ? 1 : 0);
}
throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
}
//不公开,获取以月为计时的时间
private long getProlepticMonth() {
return (year * 12L + month - 1);
}
//获取时间标准:ISO国际标准时间
@Override
public IsoChronology getChronology() {
return IsoChronology.INSTANCE;
}
//获取纪年,返回CE(Common Era)公历纪元,耶稣生年开始。BCE(Common Era)为公元前。
@Override // override for Javadoc
public Era getEra() {
return ChronoLocalDate.super.getEra();
}
public int getYear() {
return year;
}
public int getMonthValue() {
return month;
}
public Month getMonth() {
return Month.of(month);
}
public int getDayOfMonth() {
return day;
}
public int getDayOfYear() {
return getMonth().firstDayOfYear(isLeapYear()) + day - 1;
}
public DayOfWeek getDayOfWeek() {
int dow0 = (int)Math.floorMod(toEpochDay() + 3, 7);
return DayOfWeek.of(dow0 + 1);
}
//判断是否为闰年
@Override // override for Javadoc and performance
public boolean isLeapYear() {
return IsoChronology.INSTANCE.isLeapYear(year);
}
@Override
public int lengthOfMonth() {
switch (month) {
case 2:
return (isLeapYear() ? 29 : 28);
case 4:
case 6:
case 9:
case 11:
return 30;
default:
return 31;
}
}
@Override // override for Javadoc and performance
public int lengthOfYear() {
return (isLeapYear() ? 366 : 365);
}
//返回指定的日期,传入java.time.temporal.TemporalAdjusters的实现类
@Override
public LocalDate with(TemporalAdjuster adjuster) {
// optimizations
if (adjuster instanceof LocalDate) {
return (LocalDate) adjuster;
}
return (LocalDate) adjuster.adjustInto(this);
}
//返回指定修改字段后的日期
@Override
public LocalDate with(TemporalField field, long newValue) {
if (field instanceof ChronoField) {
ChronoField f = (ChronoField) field;
f.checkValidValue(newValue);
switch (f) {
case DAY_OF_WEEK: return plusDays(newValue - getDayOfWeek().getValue());
case ALIGNED_DAY_OF_WEEK_IN_MONTH: return plusDays(newValue - getLong(ALIGNED_DAY_OF_WEEK_IN_MONTH));
case ALIGNED_DAY_OF_WEEK_IN_YEAR: return plusDays(newValue - getLong(ALIGNED_DAY_OF_WEEK_IN_YEAR));
case DAY_OF_MONTH: return withDayOfMonth((int) newValue);
case DAY_OF_YEAR: return withDayOfYear((int) newValue);
case EPOCH_DAY: return LocalDate.ofEpochDay(newValue);
case ALIGNED_WEEK_OF_MONTH: return plusWeeks(newValue - getLong(ALIGNED_WEEK_OF_MONTH));
case ALIGNED_WEEK_OF_YEAR: return plusWeeks(newValue - getLong(ALIGNED_WEEK_OF_YEAR));
case MONTH_OF_YEAR: return withMonth((int) newValue);
case PROLEPTIC_MONTH: return plusMonths(newValue - getProlepticMonth());
case YEAR_OF_ERA: return withYear((int) (year >= 1 ? newValue : 1 - newValue));
case YEAR: return withYear((int) newValue);
case ERA: return (getLong(ERA) == newValue ? this : withYear(1 - year));
}
throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
}
return field.adjustInto(this, newValue);
}
//返回修改年后的日期
public LocalDate withYear(int year) {
if (this.year == year) {
return this;
}
YEAR.checkValidValue(year);
return resolvePreviousValid(year, month, day);
}
//返回修改月后的日期
public LocalDate withMonth(int month) {
if (this.month == month) {
return this;
}
MONTH_OF_YEAR.checkValidValue(month);
return resolvePreviousValid(year, month, day);
}
//返回修改日后的日期
public LocalDate withDayOfMonth(int dayOfMonth) {
if (this.day == dayOfMonth) {
return this;
}
return of(year, month, dayOfMonth);
}
//返回修改dayOfYear后的日期
public LocalDate withDayOfYear(int dayOfYear) {
if (this.getDayOfYear() == dayOfYear) {
return this;
}
return ofYearDay(year, dayOfYear);
}
//时间加上某字段后的日期,比如加上两个月localDate.plus(Period.ofMonths(2))
@Override
public LocalDate plus(TemporalAmount amountToAdd) {
if (amountToAdd instanceof Period) {
Period periodToAdd = (Period) amountToAdd;
return plusMonths(periodToAdd.toTotalMonths()).plusDays(periodToAdd.getDays());
}
Objects.requireNonNull(amountToAdd, "amountToAdd");
return (LocalDate) amountToAdd.addTo(this);
}
//时间加上某字段后的日期,比如加上两年localDate.plus(2, ChronoUnit.YEARS)
@Override
public LocalDate plus(long amountToAdd, TemporalUnit unit) {
if (unit instanceof ChronoUnit) {
ChronoUnit f = (ChronoUnit) unit;
switch (f) {
case DAYS: return plusDays(amountToAdd);
case WEEKS: return plusWeeks(amountToAdd);
case MONTHS: return plusMonths(amountToAdd);
case YEARS: return plusYears(amountToAdd);
case DECADES: return plusYears(Math.multiplyExact(amountToAdd, 10));
case CENTURIES: return plusYears(Math.multiplyExact(amountToAdd, 100));
case MILLENNIA: return plusYears(Math.multiplyExact(amountToAdd, 1000));
case ERAS: return with(ERA, Math.addExact(getLong(ERA), amountToAdd));
}
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
}
return unit.addTo(this, amountToAdd);
}
//加上年
public LocalDate plusYears(long yearsToAdd) {
if (yearsToAdd == 0) {
return this;
}
int newYear = YEAR.checkValidIntValue(year + yearsToAdd); // safe overflow
return resolvePreviousValid(newYear, month, day);
}
//加上月
public LocalDate plusMonths(long monthsToAdd) {
if (monthsToAdd == 0) {
return this;
}
long monthCount = year * 12L + (month - 1);
long calcMonths = monthCount + monthsToAdd; // safe overflow
int newYear = YEAR.checkValidIntValue(Math.floorDiv(calcMonths, 12));
int newMonth = (int)Math.floorMod(calcMonths, 12) + 1;
return resolvePreviousValid(newYear, newMonth, day);
}
//加上周
public LocalDate plusWeeks(long weeksToAdd) {
return plusDays(Math.multiplyExact(weeksToAdd, 7));
}
//加上日
public LocalDate plusDays(long daysToAdd) {
if (daysToAdd == 0) {
return this;
}
long mjDay = Math.addExact(toEpochDay(), daysToAdd);
return LocalDate.ofEpochDay(mjDay);
}
//下面同理都是减
@Override
public LocalDate minus(TemporalAmount amountToSubtract) {
if (amountToSubtract instanceof Period) {
Period periodToSubtract = (Period) amountToSubtract;
return minusMonths(periodToSubtract.toTotalMonths()).minusDays(periodToSubtract.getDays());
}
Objects.requireNonNull(amountToSubtract, "amountToSubtract");
return (LocalDate) amountToSubtract.subtractFrom(this);
}
@Override
public LocalDate minus(long amountToSubtract, TemporalUnit unit) {
return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));
}
public LocalDate minusYears(long yearsToSubtract) {
return (yearsToSubtract == Long.MIN_VALUE ? plusYears(Long.MAX_VALUE).plusYears(1) : plusYears(-yearsToSubtract));
}
public LocalDate minusMonths(long monthsToSubtract) {
return (monthsToSubtract == Long.MIN_VALUE ? plusMonths(Long.MAX_VALUE).plusMonths(1) : plusMonths(-monthsToSubtract));
}
public LocalDate minusWeeks(long weeksToSubtract) {
return (weeksToSubtract == Long.MIN_VALUE ? plusWeeks(Long.MAX_VALUE).plusWeeks(1) : plusWeeks(-weeksToSubtract));
}
public LocalDate minusDays(long daysToSubtract) {
return (daysToSubtract == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-daysToSubtract));
}
//使用指定的查询查询此瞬间
@SuppressWarnings("unchecked")
@Override
public <R> R query(TemporalQuery<R> query) {
if (query == TemporalQueries.localDate()) {
return (R) this;
}
return ChronoLocalDate.super.query(query);
}

//调整指定的时间对象,使其具有与此对象相同的日期。
@Override // override for Javadoc
public Temporal adjustInto(Temporal temporal) {
return ChronoLocalDate.super.adjustInto(temporal);
}

//根据指定的单位计算到另一个日期的时间量。
@Override
public long until(Temporal endExclusive, TemporalUnit unit) {
LocalDate end = LocalDate.from(endExclusive);
if (unit instanceof ChronoUnit) {
switch ((ChronoUnit) unit) {
case DAYS: return daysUntil(end);
case WEEKS: return daysUntil(end) / 7;
case MONTHS: return monthsUntil(end);
case YEARS: return monthsUntil(end) / 12;
case DECADES: return monthsUntil(end) / 120;
case CENTURIES: return monthsUntil(end) / 1200;
case MILLENNIA: return monthsUntil(end) / 12000;
case ERAS: return end.getLong(ERA) - getLong(ERA);
}
throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
}
return unit.between(this, end);
}

long daysUntil(LocalDate end) {
return end.toEpochDay() - toEpochDay(); // no overflow
}

private long monthsUntil(LocalDate end) {
long packed1 = getProlepticMonth() * 32L + getDayOfMonth(); // no overflow
long packed2 = end.getProlepticMonth() * 32L + end.getDayOfMonth(); // no overflow
return (packed2 - packed1) / 32;
}

//计算此日期与另一日期之间的期间作为Period
@Override
public Period until(ChronoLocalDate endDateExclusive) {
LocalDate end = LocalDate.from(endDateExclusive);
long totalMonths = end.getProlepticMonth() - this.getProlepticMonth(); // safe
int days = end.day - this.day;
if (totalMonths > 0 && days < 0) {
totalMonths--;
LocalDate calcDate = this.plusMonths(totalMonths);
days = (int) (end.toEpochDay() - calcDate.toEpochDay()); // safe
} else if (totalMonths < 0 && days > 0) {
totalMonths++;
days -= end.lengthOfMonth();
}
long years = totalMonths / 12; // safe
int months = (int) (totalMonths % 12); // safe
return Period.of(Math.toIntExact(years), months, days);
}

//使用特定的字符串格式化时间
@Override // override for Javadoc and performance
public String format(DateTimeFormatter formatter) {
Objects.requireNonNull(formatter, "formatter");
return formatter.format(this);
}

//将此日期与时间组合以创建LocalDateTime
@Override
public LocalDateTime atTime(LocalTime time) {
return LocalDateTime.of(this, time);
}
public LocalDateTime atTime(int hour, int minute) {
return atTime(LocalTime.of(hour, minute));
}
public LocalDateTime atTime(int hour, int minute, int second) {
return atTime(LocalTime.of(hour, minute, second));
}
public LocalDateTime atTime(int hour, int minute, int second, int nanoOfSecond) {
return atTime(LocalTime.of(hour, minute, second, nanoOfSecond));
}
public OffsetDateTime atTime(OffsetTime time) {
return OffsetDateTime.of(LocalDateTime.of(this, time.toLocalTime()), time.getOffset());
}

//将此日期与午夜时间相结合以创建LocalDateTime
public LocalDateTime atStartOfDay() {
return LocalDateTime.of(this, LocalTime.MIDNIGHT);
}

//根据时区中的规则,在最早的有效时间返回从该日期开始的分区日期时间。
public ZonedDateTime atStartOfDay(ZoneId zone) {
Objects.requireNonNull(zone, "zone");
// need to handle case where there is a gap from 11:30 to 00:30
// standard ZDT factory would result in 01:00 rather than 00:30
LocalDateTime ldt = atTime(LocalTime.MIDNIGHT);
if (zone instanceof ZoneOffset == false) {
ZoneRules rules = zone.getRules();
ZoneOffsetTransition trans = rules.getTransition(ldt);
if (trans != null && trans.isGap()) {
ldt = trans.getDateTimeAfter();
}
}
return ZonedDateTime.of(ldt, zone);
}
//转换为公元日(从1970年1月1日到现在经过了多少天)
@Override
public long toEpochDay() {
long y = year;
long m = month;
long total = 0;
total += 365 * y;
if (y >= 0) {
total += (y + 3) / 4 - (y + 99) / 100 + (y + 399) / 400;
} else {
total -= y / -4 - y / -100 + y / -400;
}
total += ((367 * m - 362) / 12);
total += day - 1;
if (m > 2) {
total--;
if (isLeapYear() == false) {
total--;
}
}
return total - DAYS_0000_TO_1970;
}
//与指定时间比较,调用compareTo0()
@Override // override for Javadoc and performance
public int compareTo(ChronoLocalDate other) {
if (other instanceof LocalDate) {
return compareTo0((LocalDate) other);
}
return ChronoLocalDate.super.compareTo(other);
}
//与指定时间比较
int compareTo0(LocalDate otherDate) {
int cmp = (year - otherDate.year);
if (cmp == 0) {
cmp = (month - otherDate.month);
if (cmp == 0) {
cmp = (day - otherDate.day);
}
}
return cmp;
}
//判断时间的先后,判断时间是在指定时间的前面
@Override
public boolean isAfter(ChronoLocalDate other) {
if (other instanceof LocalDate) {
return compareTo0((LocalDate) other) > 0;
}
return ChronoLocalDate.super.isAfter(other);
}
//判断时间的先后,判断时间是在指定时间的后面
@Override
public boolean isBefore(ChronoLocalDate other) {
if (other instanceof LocalDate) {
return compareTo0((LocalDate) other) < 0;
}
return ChronoLocalDate.super.isBefore(other);
}
//判断时间是否相等
@Override // override for Javadoc and performance
public boolean isEqual(ChronoLocalDate other) {
if (other instanceof LocalDate) {
return compareTo0((LocalDate) other) == 0;
}
return ChronoLocalDate.super.isEqual(other);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof LocalDate) {
return compareTo0((LocalDate) obj) == 0;
}
return false;
}
//重写时间的hashCode
@Override
public int hashCode() {
int yearValue = year;
int monthValue = month;
int dayValue = day;
return (yearValue & 0xFFFFF800) ^ ((yearValue << 11) + (monthValue << 6) + (dayValue));
}

//以{@code 2007-12-03}的形式输出字符串
@Override
public String toString() {
int yearValue = year;
int monthValue = month;
int dayValue = day;
int absYear = Math.abs(yearValue);
StringBuilder buf = new StringBuilder(10);
if (absYear < 1000) {
if (yearValue < 0) {
buf.append(yearValue - 10000).deleteCharAt(1);
} else {
buf.append(yearValue + 10000).deleteCharAt(0);
}
} else {
if (yearValue > 9999) {
buf.append('+');
}
buf.append(yearValue);
}
return buf.append(monthValue < 10 ? "-0" : "-")
.append(monthValue)
.append(dayValue < 10 ? "-0" : "-")
.append(dayValue)
.toString();
}

//使用java.time.Ser序列化时间对象
private Object writeReplace() {
return new Ser(Ser.LOCAL_DATE_TYPE, this);
}

//防止恶意的Stream,直接抛异常
private void readObject(ObjectInputStream s) throws InvalidObjectException {
throw new InvalidObjectException("Deserialization via serialization delegate");
}
//把时间写到输出流里面
void writeExternal(DataOutput out) throws IOException {
out.writeInt(year);
out.writeByte(month);
out.writeByte(day);
}
//从输出流里面读取时间创建对象
static LocalDate readExternal(DataInput in) throws IOException {
int year = in.readInt();
int month = in.readByte();
int dayOfMonth = in.readByte();
return LocalDate.of(year, month, dayOfMonth);
}

}

后记

  1. 源码是真的长,一度想放弃了。
  2. 以后源码计划,只挑重点,只挑核心。不做API翻译…
  3. 后面可能会有看一些 Spring redis nginx 等等…
  4. 新挖一个坑:数据库
  5. 尽量做到至少月更一次 (Maybe)
  6. 半入坑C#。里面的委托有点意思 类似C++函数指针。
文章作者: Shengyaqingfeng
文章链接: https://creazyboyone.github.io/LocalDateTime/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Shengyaqingfeng's Blog