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

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

索引目录

源码分析目的

项目引用

方法名称: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对象

1hutool源码分析:DateUtil(时间工具类)-当前时间和当前时间戳1hutool源码分析:DateUtil(时间工具类)-当前时间和当前时间戳1hutool源码分析:DateUtil(时间工具类)-当前时间和当前时间戳1hutool源码分析:DateUtil(时间工具类)-当前时间和当前时间戳看到这个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)**为例1hutool源码分析:DateUtil(时间工具类)-当前时间和当前时间戳1hutool源码分析:DateUtil(时间工具类)-当前时间和当前时间戳1hutool源码分析:DateUtil(时间工具类)-当前时间和当前时间戳1hutool源码分析:DateUtil(时间工具类)-当前时间和当前时间戳查了下这两个目录的差别:

因为OpenJDK里,Java标准库和部分工具的源码repo(jdk目录)里,BSD和Linux的平台相关源码都是在solaris目录里的。
原本Sun JDK的源码里平台相关的目录就是从solaris和windows这两个目录开始的,后来Unix系的平台相关代码全都放在solaris目录下了,共用大部分代码。

作者:RednaxelaFX
链接:https://www.zhihu.com/question/58982441/answer/170264788
来源:知乎

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

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;
}

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

//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;
    }

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

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

上一篇:Java虚拟机详解----JVM常见问题总结


下一篇:C# byte数组与Image的相互转换