1hutool源码分析:DateUtil(时间工具类)-当前时间和当前时间戳

简介: 1hutool源码分析:DateUtil(时间工具类)-当前时间和当前时间戳

image.png

索引目录

源码分析目的

项目引用

方法名称:DateUtil.date()

方法描述

源码分析一

传统写法一

对比

源码分析二

使用默认时区是否有风险?

避免风险最佳实践

什么是native

native的源码怎么看呢

了解不同系统下findJavaTZ_md方法执行

windows系统

unix系的平台

方法名称:DateUtil.dateSecond()

方法描述

源码分析一

方法名称:DateUtil.now()

方法描述

源码分析一

传统写法一

对比

方法名称:DateUtil.today()

方法描述

源码分析一

源码分析目的

知其然,知其所以然


项目引用

此博文的依据:hutool-5.6.5版本源码


     

cn.hutool

hutool-core

5.6.5

 

1

2

3

4

5

方法名称:DateUtil.date()

方法描述

当前时间,转换为{@link DateTime}对象


源码分析一

源码:新new了一个DateTime对象,此对象是hutool定义的时间对象,DateTime对象继承了Date对象

image.pngimage.pngimage.pngimage.png看到这个native ,说明已经挖到核心了,到了这一步,还是不清楚是怎么获取系统的默认时区的,那怎么办,JDK代码只能跟到这里。


转战OpenJDK,源码下载方式:https://gitee.com/mirrors/openjdk


3、如果再读不到,就用默认的 GMT_ID = "GMT"


避免风险最佳实践

JVM中的user.timezone变量中设置时区


什么是native

native是一个计算机函数,一个Native Method就是一个Java调用非Java代码的接口。方法的实现由非Java语言实现,比如C或C++。


native的源码怎么看呢

以**private static native String getSystemTimeZoneID(String javaHome)**为例image.pngimage.pngimage.pngimage.png查了下这两个目录的差别:

因为OpenJDK里,Java标准库和部分工具的源码repo(jdk目录)里,BSD和Linux的平台相关源码都是在solaris目录里的。
原本Sun JDK的源码里平台相关的目录就是从solaris和windows这两个目录开始的,后来Unix系的平台相关代码全都放在solaris目录下了,共用大部分代码。
作者:RednaxelaFX
链接:https://www.zhihu.com/question/58982441/answer/170264788
来源:知乎

image.pngimage.png

unix系的平台

findJavaTz_md()方法的注释上写得很清楚了:将平台时区ID映射为Java时区ID

/*
 * findJavaTZ_md() maps platform time zone ID to Java time zone ID
 * using <java_home>/lib/tzmappings. If the TZ value is not found, it
 * trys some libc implementation dependent mappings. If it still
 * can't map to a Java time zone ID, it falls back to the GMT+/-hh:mm
 * form. `country', which can be null, is not used for UNIX platforms.
 */
/*ARGSUSED1*/
char *
findJavaTZ_md(const char *java_home_dir, const char *country)
{
    char *tz;
    char *javatz = NULL;
    char *freetz = NULL;
    tz = getenv("TZ");
#ifdef __linux__
    if (tz == NULL) {
#else
#ifdef __solaris__
    if (tz == NULL || *tz == '\0') {
#endif
#endif
        tz = getPlatformTimeZoneID();
        freetz = tz;
    }
    /*
     * Remove any preceding ':'
     */
    if (tz != NULL && *tz == ':') {
        tz++;
    }
#ifdef __solaris__
    if (strcmp(tz, "localtime") == 0) {
        tz = getSolarisDefaultZoneID();
        freetz = tz;
    }
#endif
    if (tz != NULL) {
#ifdef __linux__
        /*
         * Ignore "posix/" prefix.
         */
        if (strncmp(tz, "posix/", 6) == 0) {
            tz += 6;
        }
#endif
        javatz = strdup(tz);
        if (freetz != NULL) {
            free((void *) freetz);
        }
    }
    return javatz;
}

image.pngimage.png

//CalendarUtil 类
/**
   * 获取秒级别的开始时间,即忽略毫秒部分
   *
   * @param calendar 日期 {@link Calendar}
   * @return {@link Calendar}
   * @since 4.6.2
   */
  public static Calendar beginOfSecond(Calendar calendar) {
    return truncate(calendar, DateField.SECOND);
  }
---------------------------------
    /**
   * 修改日期为某个时间字段起始时间
   *
   * @param calendar  {@link Calendar}
   * @param dateField 时间字段
   * @return 原{@link Calendar}
   */
  public static Calendar truncate(Calendar calendar, DateField dateField) {
    return DateModifier.modify(calendar, dateField.getValue(), DateModifier.ModifyType.TRUNCATE);
  }
---------------------------------
    //DateModifier类
    /**
   * 修改日期
   *
   * @param calendar {@link Calendar}
   * @param dateField 日期字段,即保留到哪个日期字段
   * @param modifyType 修改类型,包括舍去、四舍五入、进一等
   * @return 修改后的{@link Calendar}
   */
  public static Calendar modify(Calendar calendar, int dateField, ModifyType modifyType) {
    // AM_PM上下午特殊处理
    if (Calendar.AM_PM == dateField) {
      boolean isAM = DateUtil.isAM(calendar);
      switch (modifyType) {
      case TRUNCATE:
        calendar.set(Calendar.HOUR_OF_DAY, isAM ? 0 : 12);
        break;
      case CEILING:
        calendar.set(Calendar.HOUR_OF_DAY, isAM ? 11 : 23);
        break;
      case ROUND:
        int min = isAM ? 0 : 12;
        int max = isAM ? 11 : 23;
        int href = (max - min) / 2 + 1;
        int value = calendar.get(Calendar.HOUR_OF_DAY);
        calendar.set(Calendar.HOUR_OF_DAY, (value < href) ? min : max);
        break;
      }
      // 处理下一级别字段
      return modify(calendar, dateField + 1, modifyType);
    }
    // 循环处理各级字段,精确到毫秒字段
    for (int i = dateField + 1; i <= Calendar.MILLISECOND; i++) {
      if (ArrayUtil.contains(IGNORE_FIELDS, i)) {
        // 忽略无关字段(WEEK_OF_MONTH)始终不做修改
        continue;
      }
      // 在计算本周的起始和结束日时,月相关的字段忽略。
      if (Calendar.WEEK_OF_MONTH == dateField || Calendar.WEEK_OF_YEAR == dateField) {
        if (Calendar.DAY_OF_MONTH == i) {
          continue;
        }
      } else {
        // 其它情况忽略周相关字段计算
        if (Calendar.DAY_OF_WEEK == i) {
          continue;
        }
      }
      modifyField(calendar, i, modifyType);
    }
    return calendar;
  }

image.pngimage.png

image.pngimage.pngimage.pngimage.pngimage.png

目录
相关文章
|
3月前
|
Java API
Java一分钟之-Java日期与时间API:LocalDate, LocalDateTime
【5月更文挑战第13天】Java 8引入`java.time`包,改进日期时间API。`LocalDate`代表日期,`LocalDateTime`包含日期和时间。本文概述两者的基本用法、常见问题及解决策略。创建日期时间使用`of()`和`parse()`,操作日期时间有`plusDays()`、`minusMonths()`等。注意点包括:设置正确的`DateTimeFormatter`,考虑闰年影响,以及在需要时区信息时使用`ZonedDateTime`。正确使用这些类能提升代码质量。
44 3
|
9月前
性能有点不错的时间工具类
性能有点不错的时间工具类
38 0
joda-time之优雅时间计算框架
joda-time之优雅时间计算框架
Java:LocalDateTime获取今天的开始时间和结束时间
Java:LocalDateTime获取今天的开始时间和结束时间
326 0
|
Java
Java:joda-time处理时间对象
Java:joda-time处理时间对象
61 0
|
Java
Java 1.8 日期处理更方便 Time 包的LocalDateTime、LocalDate、ZonedDateTime 和Date
看到java 1.8有处理日期理方便的方法,从此可以告别以前那种获取日期的年、月、日的复杂写法 这时记录一下,方便后面查询使用
195 0
Java(九):LocalDate和LocalDateTime时间处理
Java(九):LocalDate和LocalDateTime时间处理
179 0
|
Java
Java中时间戳与Date/LocalDateTime的相互转换
Java中时间戳与Date/LocalDateTime的相互转换
351 0
Java时间工具类-获取一天的起始与结束时间
Java时间工具类-获取一天的起始与结束时间
|
Java
3hutool源码分析:DateUtil(时间工具类)-获取日期的各种内容
3hutool源码分析:DateUtil(时间工具类)-获取日期的各种内容
162 0
3hutool源码分析:DateUtil(时间工具类)-获取日期的各种内容