• Java的时间日期API


    Java为我们提供的时间日期的类有老的java.util.Date和java.util.Calender,以及新的java.time包

    java.time包基于Joda-Time库构建

    本章学习目标:

    • 掌握Java8中提供的java.time包中的常用日期类与相关方法
    • 可以从java.util包下的日期类过渡到java.time包下的日期类
    • 掌握java8中的日期与字符串之间的相互转换

    为什么会出现新的日期类API

    java.util.Date和java.util.Calender类不是线程安全的

    将java.util.Date类束之高阁才是正确之道。

                                                                    —— 鲁迅(实际是Tim Yates)

    在Java面世之初,标准库就引入了两种用于处理日期和时间的类,它们是java.util.Date和java.util.Calender,这两个类存在不少问题。

    日期计算困难

    毫秒值与日期直接转换比较繁琐,其次通过毫秒值来计算时间的差额步骤较多

    /**
     *   程序员小李出生于1995年12月16日,计算当前这个时间他已经出生了多少天?
     *   步骤:
     *       1.初始化Date对象,无参构造(无参构造默认代表的就是当前时间)
     *       2.获取当前时间距离1970年1月1日过了多少毫秒
     *       3.初始化Calender对象并设时间为1995年12月16日,并将Calender对象转为Date对象,再转换为距离1970年1月1日过了多少毫秒
     *       4.将两个毫秒数相减,然后将毫秒转为天数
     **/
    public class JavaUtilTimeCalculateDemo {
        public static void main(String[] args) {
            Date date = new Date();
            long s1 = date.getTime(); // 获取当前时间距离1970年1月1日过了多少毫秒
    
            Calendar calendar = Calendar.getInstance();
            calendar.set(1995, 11, 16); // 这里的第二个参数是月,月从0开始,因此这里要写11。这里由于混乱,非常容易犯错。
    
            Date date1 = calendar.getTime();
            long s2 = date1.getTime();
    
            long intervalDays = (s1 - s2)/1000/60/60/24;
            System.out.println("1995年12月16日距离现在已经过了"+intervalDays+"天");
        }
    }

    结果

    1995年12月16日距离现在已经过了9041天

    使用新版本API

    public class JavaUtilTimeCalculateDemo {
        public static void main(String[] args) {
            long days = ChronoUnit.DAYS.between(LocalDate.of(1995, 12, 16), LocalDate.now());
            System.out.println("1995年12月16日距离现在已经过了"+days+"天");
        }
    }

    结果

    1995年12月16日距离现在已经过了9042天

    新版本计算结果是正确的,老版本不仅繁琐还容易出错

    线程安全问题

    /**
     *  创建十个线程,将字符串"2018-12-12 12:12:12"转换为Date对象后打印到控制台上
     **/
    public class SimpleDateFormatUnSafeDemo {
        final static SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
        public static void main(String[] args) {
            // 循环十次,创建是个线程对象并启动
            for (int i=0; i<10; i++){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try{
                            Date date = SIMPLE_DATE_FORMAT.parse("2018-12-12 12:12:12");
                            System.out.println(date);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        }
    }

    IDEA控制台结果:

    D:programfilesjdk8injava.exe "-javaagent:D:programfilesIntelliJ IDEA 2020.1libidea_rt.jar=10259:D:programfilesIntelliJ IDEA 2020.1in" -Dfile.encoding=UTF-8 -classpath D:programfilesjdk8jrelibcharsets.jar;D:programfilesjdk8jrelibdeploy.jar;D:programfilesjdk8jrelibextaccess-bridge-64.jar;D:programfilesjdk8jrelibextcldrdata.jar;D:programfilesjdk8jrelibextdnsns.jar;D:programfilesjdk8jrelibextjaccess.jar;D:programfilesjdk8jrelibextjfxrt.jar;D:programfilesjdk8jrelibextlocaledata.jar;D:programfilesjdk8jrelibext
    ashorn.jar;D:programfilesjdk8jrelibextsunec.jar;D:programfilesjdk8jrelibextsunjce_provider.jar;D:programfilesjdk8jrelibextsunmscapi.jar;D:programfilesjdk8jrelibextsunpkcs11.jar;D:programfilesjdk8jrelibextzipfs.jar;D:programfilesjdk8jrelibjavaws.jar;D:programfilesjdk8jrelibjce.jar;D:programfilesjdk8jrelibjfr.jar;D:programfilesjdk8jrelibjfxswt.jar;D:programfilesjdk8jrelibjsse.jar;D:programfilesjdk8jrelibmanagement-agent.jar;D:programfilesjdk8jrelibplugin.jar;D:programfilesjdk8jrelib
    esources.jar;D:programfilesjdk8jrelib
    t.jar;D:gitprojectsDataAnalySystemCommon	argetclasses;C:UsersMy.m2
    epositorycnhutoolhutool-all5.4.2hutool-all-5.4.2.jar;C:UsersMy.m2
    epositorycomalibabafastjson1.2.58fastjson-1.2.58.jar;C:UsersMy.m2
    epositoryorgapachehbasehbase-client2.0.0hbase-client-2.0.0.jar;C:UsersMy.m2
    epositoryorgapachehbase	hirdpartyhbase-shaded-protobuf2.1.0hbase-shaded-protobuf-2.1.0.jar;C:UsersMy.m2
    epositoryorgapachehbasehbase-common2.0.0hbase-common-2.0.0.jar;C:UsersMy.m2
    epositorycomgithubstephencfindbugsfindbugs-annotations1.3.9-1findbugs-annotations-1.3.9-1.jar;C:UsersMy.m2
    epositoryorgapachehbasehbase-hadoop-compat2.0.0hbase-hadoop-compat-2.0.0.jar;C:UsersMy.m2
    epositoryorgapachehbasehbase-metrics-api2.0.0hbase-metrics-api-2.0.0.jar;C:UsersMy.m2
    epositoryorgapachehbasehbase-hadoop2-compat2.0.0hbase-hadoop2-compat-2.0.0.jar;C:UsersMy.m2
    epositoryorgapachehbasehbase-metrics2.0.0hbase-metrics-2.0.0.jar;C:UsersMy.m2
    epositoryorgapachehbasehbase-protocol-shaded2.0.0hbase-protocol-shaded-2.0.0.jar;C:UsersMy.m2
    epositoryorgapachehbasehbase-protocol2.0.0hbase-protocol-2.0.0.jar;C:UsersMy.m2
    epositoryjunitjunit4.12junit-4.12.jar;C:UsersMy.m2
    epositoryorghamcresthamcrest-core1.3hamcrest-core-1.3.jar;C:UsersMy.m2
    epositorycommons-codeccommons-codec1.11commons-codec-1.11.jar;C:UsersMy.m2
    epositorycommons-iocommons-io2.5commons-io-2.5.jar;C:UsersMy.m2
    epositoryorgapachecommonscommons-lang33.7commons-lang3-3.7.jar;C:UsersMy.m2
    epositoryorgslf4jslf4j-api1.7.25slf4j-api-1.7.25.jar;C:UsersMy.m2
    epositoryorgapachehbase	hirdpartyhbase-shaded-miscellaneous2.1.0hbase-shaded-miscellaneous-2.1.0.jar;C:UsersMy.m2
    epositorycomgoogleprotobufprotobuf-java2.5.0protobuf-java-2.5.0.jar;C:UsersMy.m2
    epositoryorgapachehbase	hirdpartyhbase-shaded-netty2.1.0hbase-shaded-netty-2.1.0.jar;C:UsersMy.m2
    epositoryorgapachezookeeperzookeeper3.4.10zookeeper-3.4.10.jar;C:UsersMy.m2
    epositoryorgapachehtracehtrace-core44.2.0-incubatinghtrace-core4-4.2.0-incubating.jar;C:UsersMy.m2
    epositoryorgjrubyjcodingsjcodings1.0.18jcodings-1.0.18.jar;C:UsersMy.m2
    epositoryorgjrubyjonijoni2.1.11joni-2.1.11.jar;C:UsersMy.m2
    epositoryiodropwizardmetricsmetrics-core3.2.6metrics-core-3.2.6.jar;C:UsersMy.m2
    epositoryorgapachecommonscommons-crypto1.0.0commons-crypto-1.0.0.jar;C:UsersMy.m2
    epositorycomfasterxmljacksoncorejackson-databind2.9.5jackson-databind-2.9.5.jar;C:UsersMy.m2
    epositorycomfasterxmljacksoncorejackson-annotations2.9.0jackson-annotations-2.9.0.jar;C:UsersMy.m2
    epositoryorgapachehadoophadoop-auth2.7.4hadoop-auth-2.7.4.jar;C:UsersMy.m2
    epositoryorgapachedirectoryserverapacheds-kerberos-codec2.0.0-M15apacheds-kerberos-codec-2.0.0-M15.jar;C:UsersMy.m2
    epositoryorgapachedirectoryserverapacheds-i18n2.0.0-M15apacheds-i18n-2.0.0-M15.jar;C:UsersMy.m2
    epositoryorgapachedirectoryapiapi-asn1-api1.0.0-M20api-asn1-api-1.0.0-M20.jar;C:UsersMy.m2
    epositoryorgapachedirectoryapiapi-util1.0.0-M20api-util-1.0.0-M20.jar;C:UsersMy.m2
    epositoryorgapachehadoophadoop-common2.7.4hadoop-common-2.7.4.jar;C:UsersMy.m2
    epositoryorgapachehadoophadoop-annotations2.7.4hadoop-annotations-2.7.4.jar;C:UsersMy.m2
    epositorycommons-clicommons-cli1.2commons-cli-1.2.jar;C:UsersMy.m2
    epositoryorgapachecommonscommons-math33.1.1commons-math3-3.1.1.jar;C:UsersMy.m2
    epositoryxmlencxmlenc.52xmlenc-0.52.jar;C:UsersMy.m2
    epositorycommons-netcommons-net3.1commons-net-3.1.jar;C:UsersMy.m2
    epositorycommons-collectionscommons-collections3.2.2commons-collections-3.2.2.jar;C:UsersMy.m2
    epositoryorgmortbayjettyjetty-sslengine6.1.26jetty-sslengine-6.1.26.jar;C:UsersMy.m2
    epositorycommons-langcommons-lang2.6commons-lang-2.6.jar;C:UsersMy.m2
    epositorycommons-configurationcommons-configuration1.6commons-configuration-1.6.jar;C:UsersMy.m2
    epositorycommons-digestercommons-digester1.8commons-digester-1.8.jar;C:UsersMy.m2
    epositorycommons-beanutilscommons-beanutils1.7.0commons-beanutils-1.7.0.jar;C:UsersMy.m2
    epositorycommons-beanutilscommons-beanutils-core1.8.0commons-beanutils-core-1.8.0.jar;C:UsersMy.m2
    epositoryorgcodehausjacksonjackson-core-asl1.9.13jackson-core-asl-1.9.13.jar;C:UsersMy.m2
    epositoryorgcodehausjacksonjackson-mapper-asl1.9.13jackson-mapper-asl-1.9.13.jar;C:UsersMy.m2
    epositoryorgapacheavroavro1.7.4avro-1.7.4.jar;C:UsersMy.m2
    epositorycom	houghtworksparanamerparanamer2.3paranamer-2.3.jar;C:UsersMy.m2
    epositorycomgooglecodegsongson2.8.4gson-2.8.4.jar;C:UsersMy.m2
    epositorycomjcraftjsch.1.54jsch-0.1.54.jar;C:UsersMy.m2
    epositoryorgapachecuratorcurator-client2.7.1curator-client-2.7.1.jar;C:UsersMy.m2
    epositoryorgapachecuratorcurator-recipes4.0.1curator-recipes-4.0.1.jar;C:UsersMy.m2
    epositorycomgooglecodefindbugsjsr3053.0.0jsr305-3.0.0.jar;C:UsersMy.m2
    epositoryorgapacheyetusaudience-annotations.5.0audience-annotations-0.5.0.jar;C:UsersMy.m2
    epositoryorgapachekafkakafka-clients2.1.0kafka-clients-2.1.0.jar;C:UsersMy.m2
    epositorycomgithublubenzstd-jni1.3.5-4zstd-jni-1.3.5-4.jar;C:UsersMy.m2
    epositoryorglz4lz4-java1.5.0lz4-java-1.5.0.jar;C:UsersMy.m2
    epositoryorgxerialsnappysnappy-java1.1.7.2snappy-java-1.1.7.2.jar;C:UsersMy.m2
    epository
    uyandexclickhouseclickhouse-jdbc.1.40clickhouse-jdbc-0.1.40.jar;C:UsersMy.m2
    epositoryorgapachehttpcomponentshttpclient4.5.5httpclient-4.5.5.jar;C:UsersMy.m2
    epositoryorgapachehttpcomponentshttpmime4.5.5httpmime-4.5.5.jar;C:UsersMy.m2
    epository
    etjpountzlz4lz41.3.0lz4-1.3.0.jar;C:UsersMy.m2
    epositorycomfasterxmljacksoncorejackson-core2.9.5jackson-core-2.9.5.jar;C:UsersMy.m2
    epositorycomgoogleguavaguava19.0guava-19.0.jar;C:UsersMy.m2
    epositoryjoda-timejoda-time2.9.9joda-time-2.9.9.jar;C:UsersMy.m2
    epositoryorgapachehivehive-exec1.1.0hive-exec-1.1.0.jar;C:UsersMy.m2
    epositoryorgapachehivehive-ant1.1.0hive-ant-1.1.0.jar;C:UsersMy.m2
    epositoryorgapachevelocityvelocity1.5velocity-1.5.jar;C:UsersMy.m2
    epositoryorooro2.0.8oro-2.0.8.jar;C:UsersMy.m2
    epositoryorgapachehivehive-metastore1.1.0hive-metastore-1.1.0.jar;C:UsersMy.m2
    epositorycomjolboxonecp.8.0.RELEASEonecp-0.8.0.RELEASE.jar;C:UsersMy.m2
    epositoryorgapachederbyderby10.14.1.0derby-10.14.1.0.jar;C:UsersMy.m2
    epositoryorgdatanucleusdatanucleus-api-jdo3.2.6datanucleus-api-jdo-3.2.6.jar;C:UsersMy.m2
    epositoryorgdatanucleusdatanucleus-rdbms3.2.9datanucleus-rdbms-3.2.9.jar;C:UsersMy.m2
    epositorycommons-poolcommons-pool1.6commons-pool-1.6.jar;C:UsersMy.m2
    epositorycommons-dbcpcommons-dbcp1.4commons-dbcp-1.4.jar;C:UsersMy.m2
    epositoryjavaxjdojdo-api3.0.1jdo-api-3.0.1.jar;C:UsersMy.m2
    epositoryjavax	ransactionjta1.1jta-1.1.jar;C:UsersMy.m2
    epositoryorgapachehivehive-shims1.1.0hive-shims-1.1.0.jar;C:UsersMy.m2
    epositoryorgapachehiveshimshive-shims-common1.1.0hive-shims-common-1.1.0.jar;C:UsersMy.m2
    epositoryorgapachehiveshimshive-shims-0.20S1.1.0hive-shims-0.20S-1.1.0.jar;C:UsersMy.m2
    epositoryorgapachehiveshimshive-shims-0.231.1.0hive-shims-0.23-1.1.0.jar;C:UsersMy.m2
    epositoryorgapachehadoophadoop-yarn-server-resourcemanager2.6.0hadoop-yarn-server-resourcemanager-2.6.0.jar;C:UsersMy.m2
    epositorycomgoogleinjectextensionsguice-servlet3.0guice-servlet-3.0.jar;C:UsersMy.m2
    epositorycomgoogleinjectguice3.0guice-3.0.jar;C:UsersMy.m2
    epositoryjavaxinjectjavax.inject1javax.inject-1.jar;C:UsersMy.m2
    epositoryaopallianceaopalliance1.0aopalliance-1.0.jar;C:UsersMy.m2
    epositorycomsunjerseyjersey-json1.9jersey-json-1.9.jar;C:UsersMy.m2
    epositorycomsunxmlindjaxb-impl2.2.3-1jaxb-impl-2.2.3-1.jar;C:UsersMy.m2
    epositoryorgcodehausjacksonjackson-jaxrs1.8.3jackson-jaxrs-1.8.3.jar;C:UsersMy.m2
    epositoryorgcodehausjacksonjackson-xc1.8.3jackson-xc-1.8.3.jar;C:UsersMy.m2
    epositorycomsunjerseycontribsjersey-guice1.9jersey-guice-1.9.jar;C:UsersMy.m2
    epositorycomsunjerseyjersey-server1.19.1jersey-server-1.19.1.jar;C:UsersMy.m2
    epositoryorgapachehadoophadoop-yarn-common2.6.0hadoop-yarn-common-2.6.0.jar;C:UsersMy.m2
    epositoryorgapachehadoophadoop-yarn-api2.6.0hadoop-yarn-api-2.6.0.jar;C:UsersMy.m2
    epositoryjavaxxmlindjaxb-api2.3.0jaxb-api-2.3.0.jar;C:UsersMy.m2
    epositoryorgcodehausjettisonjettison1.1jettison-1.1.jar;C:UsersMy.m2
    epositorycomsunjerseyjersey-core1.19.1jersey-core-1.19.1.jar;C:UsersMy.m2
    epositoryjavaxws
    sjsr311-api1.1.1jsr311-api-1.1.1.jar;C:UsersMy.m2
    epositorycomsunjerseyjersey-client1.19.1jersey-client-1.19.1.jar;C:UsersMy.m2
    epositoryorgmortbayjettyjetty-util6.1.26jetty-util-6.1.26.jar;C:UsersMy.m2
    epositoryorgapachehadoophadoop-yarn-server-common2.6.0hadoop-yarn-server-common-2.6.0.jar;C:UsersMy.m2
    epositoryorgfusesourceleveldbjnileveldbjni-all1.8leveldbjni-all-1.8.jar;C:UsersMy.m2
    epositoryorgapachehadoophadoop-yarn-server-applicationhistoryservice2.6.0hadoop-yarn-server-applicationhistoryservice-2.6.0.jar;C:UsersMy.m2
    epositoryorgapachehadoophadoop-yarn-server-web-proxy2.6.0hadoop-yarn-server-web-proxy-2.6.0.jar;C:UsersMy.m2
    epositoryorgmortbayjettyjetty6.1.26jetty-6.1.26.jar;C:UsersMy.m2
    epositoryorgapachehiveshimshive-shims-scheduler1.1.0hive-shims-scheduler-1.1.0.jar;C:UsersMy.m2
    epositorycommons-httpclientcommons-httpclient3.0.1commons-httpclient-3.0.1.jar;C:UsersMy.m2
    epositorycommons-loggingcommons-logging1.1.3commons-logging-1.1.3.jar;C:UsersMy.m2
    epositorylog4jlog4j1.2.16log4j-1.2.16.jar;C:UsersMy.m2
    epositorylog4japache-log4j-extras1.2.17apache-log4j-extras-1.2.17.jar;C:UsersMy.m2
    epositoryorgantlrantlr-runtime3.4antlr-runtime-3.4.jar;C:UsersMy.m2
    epositoryorgantlrstringtemplate3.2.1stringtemplate-3.2.1.jar;C:UsersMy.m2
    epositoryantlrantlr2.7.7antlr-2.7.7.jar;C:UsersMy.m2
    epositoryorgantlrST44.0.4ST4-4.0.4.jar;C:UsersMy.m2
    epositoryorgapacheantant1.9.1ant-1.9.1.jar;C:UsersMy.m2
    epositoryorgapacheantant-launcher1.9.1ant-launcher-1.9.1.jar;C:UsersMy.m2
    epositoryorgapachecommonscommons-compress1.4.1commons-compress-1.4.1.jar;C:UsersMy.m2
    epositoryorg	ukaanixz1.0xz-1.0.jar;C:UsersMy.m2
    epositoryorgapache	hriftlibfb303.9.2libfb303-0.9.2.jar;C:UsersMy.m2
    epositoryorgapachecuratorcurator-framework4.0.1curator-framework-4.0.1.jar;C:UsersMy.m2
    epositoryorgcodehausgroovygroovy-all2.4.15groovy-all-2.4.15.jar;C:UsersMy.m2
    epositoryorgdatanucleusdatanucleus-core3.2.10datanucleus-core-3.2.10.jar;C:UsersMy.m2
    epositoryorgapachecalcitecalcite-core1.0.0-incubatingcalcite-core-1.0.0-incubating.jar;C:UsersMy.m2
    epositoryorgapachecalcitecalcite-linq4j1.0.0-incubatingcalcite-linq4j-1.0.0-incubating.jar;C:UsersMy.m2
    epositoryeigenbaseeigenbase-properties1.1.4eigenbase-properties-1.1.4.jar;C:UsersMy.m2
    epositoryorgcodehausjaninojanino3.0.8janino-3.0.8.jar;C:UsersMy.m2
    epositoryorgcodehausjaninocommons-compiler2.7.6commons-compiler-2.7.6.jar;C:UsersMy.m2
    epositoryorgapachecalcitecalcite-avatica1.0.0-incubatingcalcite-avatica-1.0.0-incubating.jar;C:UsersMy.m2
    epositorystaxstax-api1.0.1stax-api-1.0.1.jar;C:UsersMy.m2
    epositoryjlinejline2.12jline-2.12.jar;C:UsersMy.m2
    epositoryorgslf4jslf4j-log4j121.7.25slf4j-log4j12-1.7.25.jar;C:UsersMy.m2
    epositoryorgapachehivehive-jdbc1.1.0hive-jdbc-1.1.0.jar;C:UsersMy.m2
    epositoryorgapachehivehive-common1.1.0hive-common-1.1.0.jar;C:UsersMy.m2
    epositoryorgapachehivehive-service1.1.0hive-service-1.1.0.jar;C:UsersMy.m2
    epository
    etsfjpamjpam1.1jpam-1.1.jar;C:UsersMy.m2
    epositoryorgeclipsejettyaggregatejetty-all7.6.0.v20120127jetty-all-7.6.0.v20120127.jar;C:UsersMy.m2
    epositoryjavaxservletservlet-api2.5servlet-api-2.5.jar;C:UsersMy.m2
    epositoryorgapachegeronimospecsgeronimo-jta_1.1_spec1.1.1geronimo-jta_1.1_spec-1.1.1.jar;C:UsersMy.m2
    epositoryjavaxmailmail1.4.1mail-1.4.1.jar;C:UsersMy.m2
    epositoryjavaxactivationactivation1.1activation-1.1.jar;C:UsersMy.m2
    epositoryorgapachegeronimospecsgeronimo-jaspic_1.0_spec1.0geronimo-jaspic_1.0_spec-1.0.jar;C:UsersMy.m2
    epositoryorgapachegeronimospecsgeronimo-annotation_1.0_spec1.1.1geronimo-annotation_1.0_spec-1.1.1.jar;C:UsersMy.m2
    epositoryasmasm-commons3.1asm-commons-3.1.jar;C:UsersMy.m2
    epositoryasmasm-tree3.1asm-tree-3.1.jar;C:UsersMy.m2
    epositoryasmasm3.1asm-3.1.jar;C:UsersMy.m2
    epositoryorgapachehivehive-serde1.1.0hive-serde-1.1.0.jar;C:UsersMy.m2
    epository
    etsfopencsvopencsv2.3opencsv-2.3.jar;C:UsersMy.m2
    epositorycom	witterparquet-hadoop-bundle1.6.0rc3parquet-hadoop-bundle-1.6.0rc3.jar;C:UsersMy.m2
    epositoryorgapachehttpcomponentshttpcore4.4.9httpcore-4.4.9.jar;C:UsersMy.m2
    epositoryorgapache	hriftlibthrift.9.2libthrift-0.9.2.jar com.aidata.utils.SimpleDateFormatUnSafeDemo
    Exception in thread "Thread-1" java.lang.NumberFormatException: empty String
        at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1842)
        at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
        at java.lang.Double.parseDouble(Double.java:538)
        at java.text.DigitList.getDouble(DigitList.java:169)
        at java.text.DecimalFormat.parse(DecimalFormat.java:2089)
        at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1869)
        at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
        at java.text.DateFormat.parse(DateFormat.java:364)
        at com.aidata.utils.SimpleDateFormatUnSafeDemo$1.run(SimpleDateFormatUnSafeDemo.java:27)
        at java.lang.Thread.run(Thread.java:748)
    Wed Dec 12 12:12:12 GMT+08:00 2018
    Wed Dec 12 12:12:12 GMT+08:00 2018
    Wed Dec 12 12:12:12 GMT+08:00 2018
    Wed Dec 12 12:12:12 GMT+08:00 2018
    Wed Dec 12 12:12:12 GMT+08:00 2018
    Wed Dec 12 12:12:12 GMT+08:00 2018
    Wed Dec 12 12:12:12 GMT+08:00 2018
    Wed Dec 12 12:12:12 GMT+08:00 2018
    Wed Dec 12 12:12:12 GMT+08:00 2018
    
    Process finished with exit code 0

    第27行报错,即标黄的那一行

    全局使用同一个Calender对象,如果线程没有同步措施的话,很可能会造成线程安全问题

     如,线程一执行上面红色代码,线程二得到执行下面黄色代码,当线程一继续执行时,数据已被线程二清空,此时会报错。

    解决

    /**
     *  创建十个线程,将字符串"2018-12-12 12:12:12"转换为Date对象后打印到控制台上
     **/
    public class SimpleDateFormatUnSafeDemo {
        final static SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
        public static void main(String[] args) {
            // 循环十次,创建是个线程对象并启动
            for (int i=0; i<10; i++){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try{
                            synchronized (SIMPLE_DATE_FORMAT){
                                Date date = SIMPLE_DATE_FORMAT.parse("2018-12-12 12:12:12");
                                System.out.println(date);
                            }
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        }
    }

    另外,java.util.Date和java.util.Calender类之前,枚举类型(ENUM)还没有出现,所以字段中使用整数常量导致整数常量都是可变的,而不是线程安全的。为了处理实际开发中遇到的问题,标准库随后引入了java.sql.Data作为java.util.Date的子类,但还是没有彻底解决问题。

    Java8新日期时间类的使用

    Instant类

    • 对时间轴上的单一瞬时点建模,可以用于记录应用程序中的事件时间戳,在之后学习的类型转换中,均可以使用Instant类作为中间类完成转换。

    Duration类

    • 表示秒或纳秒时间间隔,适合处理较短时间,需要更高的精确性 秒杀

    Period类

    • 表示一段时间的年、月、日

    LocalDate类

    • 是一个不可变的日期时间对象,表示日期,通常视为年月日 final修饰

    LocalTime类

    • 是一个不可变的日期时间对象,表示时间,通常视为时分秒,时间表示为纳秒精度

    LocalDateTime类

    • 是一个不可变的日期时间对象,代表日期时间,通常视为年月日时分秒

    ZonedDateTime类

    • 是具有失去的日期时间的不可变表示,此类存储所有日期和时间字段,精度为纳秒,时区为区域偏移量,用于处理模糊的本地日期时间。

    创建对象

    now()方法

    所有类均生成不可变的实例,它们是线程安全的,这些类不提供公共构造函数,也就是说没办法通过new创建,需要采用工厂方法实例化。

    now方法可以根据当前日期和时间创建实例

    public class Java8TimeDateDemo {
        public static void main(String[] args) {
            Instant instant = Instant.now();
            LocalDate localDate = LocalDate.now();
            LocalTime localTime = LocalTime.now();
            LocalDateTime localDateTime = LocalDateTime.now();
            ZonedDateTime zonedDateTime = ZonedDateTime.now();
    
            System.out.println("Instant: "+instant);
            System.out.println("LocalDate: "+localDate);
            System.out.println("LocalTime: "+localTime);
            System.out.println("LocalDateTime: "+localDateTime);
            System.out.println("ZonedDateTime: "+zonedDateTime);
        }
    }

    toSring方法都被重写了

    结果

    Instant: 2020-09-17T02:13:50.354Z 国际标准时
    LocalDate: 2020-09-17
    LocalTime: 10:13:50.377
    LocalDateTime: 2020-09-17T10:13:50.378
    ZonedDateTime: 2020-09-17T10:13:50.380+08:00[GMT+08:00]
    public class Java8TimeDateDemo {
        public static void main(String[] args) {
            // 使用now方法创建Year类的实例对象
            Year year = Year.now();
            // 使用now方法创建YearMonth类的实例对象
            YearMonth yearMonth = YearMonth.now();
            // 使用now方法创建MonthDay的实例对象
            MonthDay monthDay = MonthDay.now();
    
            System.out.println("year: "+year);
            System.out.println("yearMonth: "+yearMonth);
            System.out.println("monthDay: "+monthDay);
        }
    }

    结果

    year: 2020
    yearMonth: 2020-09
    monthDay: --09-17

    of()方法

    上面的now都是当前时间节点,想要指定时间节点怎么办呢?

    of方法可以根据给定的参数生成对应的日期/时间对象,基本上每个基本类都有of方法用于生成的对应的对象,而且重载形式多变,可以根据不同的参数生成对应的数据。

    public class Java8TimeDateDemo {
        public static void main(String[] args) {
            /**
             * 初始化2018年8月8日的LocalDate对象
             */
            LocalDate localDate = LocalDate.of(2018, 8, 8);
            System.out.println("LocalDate: " + localDate);
    
            /**
             * 初始化晚上8点0分0秒的LocalTime对象 -> 如果是晚上的时间,需要加12
             * LocalTime.of 方法的重载形式有以下几种:
             *     LocalTime.of(int hour, int minute) -> 根据小时/分钟生成对象
             *     LocalTime.of(int hour, int minute, int second)
             *     LocalTime.of(int hour, int minute, int second, int nanOfSecond)
             * 注意:如果秒和纳秒是0的话,那么默认不会封装这些数据,只显示小时和分钟
             */
            LocalTime localTime = LocalTime.of(20, 0);
            System.out.println("LocalTime: " + localTime);
    
            /**
             * 初始化2018年8月8日下午8点0分的LocalDateTime对象
             * LocalDateTime.of方法重载形式有以下几种:
             *     LocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanOfSecond)
             *     LocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute)
             */
            LocalDateTime localDateTime = LocalDateTime.of(2018,8,8,20,0);
            System.out.println("LocalDateTime: " + localDateTime);
    
            /**
             * LodalDateTime的of方法特殊使用:
             *     LocalDateTime of(LocalDate date, LocalTime time)
             */
            LocalDate date = LocalDate.of(2020, 9, 18);
            LocalTime time = LocalTime.of(20, 0);
            LocalDateTime dateTime = LocalDateTime.of(date, time);
            System.out.println("SpecialLocalDateTime: " + dateTime);
        }
    }

    结果

    LocalDate: 2018-08-08
    LocalTime: 20:00
    LocalDateTime: 2018-08-08T20:00
    SpecialLocalDateTime: 2020-09-18T20:00

    为LocalDateTime添加时区信息

    ZonedDateTime对象里面封装的不仅有时间日期,并且还有偏移量+时区,那么时区如何在java中获取呢?通过提供的一个类ZoneId的getAvailableZoneIds方法可以获取到一个Set集合,集合中封装了600个时区。

    获取所有时区

    public class Java8TimeDateDemo {
        public static void main(String[] args) {
            Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
            for (String zoneId: availableZoneIds){
                System.out.println(zoneId);
            }
        }
    }

    当前系统默认时区

            ZoneId zoneId = ZoneId.systemDefault();
            System.out.println(zoneId);

    可以通过给LocalDateTime添加时区来查看不同时区的时间,添加纽约的时区:

    • 封装时间LocalDateTime并添加时区信息
    • 更改时区信息查看对应的时间
    public class Java8TimeDateDemo {
        public static void main(String[] args) {
            // 1.封装LocalDateTime对象,参数自定义 -> 2018年11月11日 8点54分38秒
            LocalDateTime localDateTime = LocalDateTime.of(2018, 11, 11, 8, 54, 38);
    
            // 2.上面只是封装了时间,并没有时区相关的数据,所以要添加时区信息到对象中,使用atZone()方法
            ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.of("Asia/Shanghai"));
            System.out.println("Asia/Shanghai时区当前时间是: " + zonedDateTime);
    
            // 3.更改时区查看其他时区当前时间,通过withZoneSameInstant()方法即可更改
            ZonedDateTime tokyoZonedDateTime = zonedDateTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
            System.out.println("同一时刻,Asia/Tokyo时区当前时间是: " + tokyoZonedDateTime);
    
        }
    }

    结果

    Asia/Shanghai时区当前时间是: 2018-11-11T08:54:38+08:00[Asia/Shanghai]
    同一时刻,Asia/Tokyo时区当前时间是: 2018-11-11T09:54:38+09:00[Asia/Tokyo]

    Month枚举类

    Month中包含了标准日历中的12个月份的常量(JANUARY-DECEMBER),也提供了一些方便的方法供我们使用。、

    推荐在初始化LocalDate和LocalDateTime对象的时候,使用枚举的方式传入月份参数。

    public class Java8TimeDateDemo {
        public static void main(String[] args) {
    
            LocalDateTime localDateTime = LocalDateTime.of(2011, Month.NOVEMBER, 12, 17, 1);
            System.out.println(localDateTime);
    
            Month month = Month.of(12);
            System.out.println(month);
    
        }
    }

    Java枚举(enum)详解:Java声明枚举类型、枚举(enum)类、EnumMap 与 EnumSet

    根据现有实例创建日期与时间对象

    LocalDate、LocalTime、LocalDateTime一旦创建无法修改,不可改变,有利于线程安全。

    想要修改某个日期/时间对象的现有实例时,可以使用plus和minus方法。返回的都是新的对象。

    public class Java8TimeDateDemo {
        public static void main(String[] args) {
            LocalDate localDate = LocalDate.of(2016, 2, 12);
            System.out.println("当前时间是: " + localDate);
    
            LocalDate localDate1 = localDate.plusDays(4);
            System.out.println(localDate1 == localDate);
    
        }
    }

    结果

    当前时间是: 2016-02-12
    false

    plusXxx方法

    plus方法

    /**
     * 小占查看自己的保险记录的时候看到还有2年3月8天就到期了,计算到期的时间是什么时候?
     */
    public class Java8TimeDateDemo {
        public static void main(String[] args) {
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime endTime = now.plusYears(2).plusMonths(3).plusDays(8);
            System.out.println("当前时间是: " + now + ",到期时间是: " + endTime);
        }
    }

    结果

    当前时间是: 2020-09-17T11:23:53.862,到期时间是: 2022-12-25T11:23:53.862

    我们可以直接使用plus方法

    plus(TemporalAmount amount)

    TemporalAmount是一个接口,Period实现了这个接口

    public class Java8TimeDateDemo {
        public static void main(String[] args) {
            LocalDateTime now = LocalDateTime.now();
    
            Period period = Period.of(2, 3, 8);
            LocalDateTime endTime1 = now.plus(period);
            System.out.println("当前时间是: " + now + ",到期时间是: " + endTime1);
        }
    }

    结果一样

     plus(long l, TemporaUnit unit) ,在实际开发中,可能还会更精准地去操作日期或者增加一些特殊的时间,如1个世纪,1个半天,10年等,Java8提供了这些日期的表示方式。

     TemporaUnit 是一个接口,可以使用实现类 ChronoUnit ,封装了很多时间段

    CENTURIES
    Unit that represents the concept of a century.
    DAYS
    Unit that represents the concept of a day.
    DECADES
    Unit that represents the concept of a decade.
    ERAS
    Unit that represents the concept of an era.
    FOREVER
    Artificial unit that represents the concept of forever.
    HALF_DAYS
    Unit that represents the concept of half a day, as used in AM/PM.
    HOURS
    Unit that represents the concept of an hour.
    MICROS
    Unit that represents the concept of a microsecond.
    MILLENNIA
    Unit that represents the concept of a millennium.
    MILLIS
    Unit that represents the concept of a millisecond.
    MINUTES
    Unit that represents the concept of a minute.
    MONTHS
    Unit that represents the concept of a month.
    NANOS
    Unit that represents the concept of a nanosecond, the smallest supported unit of time.
    SECONDS
    Unit that represents the concept of a second.
    WEEKS
    Unit that represents the concept of a week.
    YEARS
    Unit that represents the concept of a year.
    /**
     * 结婚十年被称为锡婚,2020年2月2日11点11分11秒被称为对称日,如果该天结婚,锡婚会发生在什么时候?
     */
    public class Java8TimeDateDemo {
        public static void main(String[] args) {
            LocalDateTime marryTime = LocalDateTime.of(2020, Month.FEBRUARY, 2, 11, 11, 11);
            LocalDateTime tinAnniversary = marryTime.plus(1, ChronoUnit.DECADES);
            System.out.println("锡婚发生在: " + tinAnniversary);
            // 锡婚后半天需要请客吃饭,半天的时间节点
            LocalDateTime treatTime = tinAnniversary.plus(1, ChronoUnit.HALF_DAYS);
            System.out.println("请客吃饭的时间: " + treatTime);
        }
    }

    结果

    锡婚发生在: 2030-02-02T11:11:11
    请客吃饭的时间: 2030-02-02T23:11:11

    with方法

    不需要对日期进行加减而是直接修改,用with方法

    LocalDateTime withNano(int i) 修改纳秒,下同
    LocalDateTime withSecond(int i)
    LocalDateTime withMinute(int i)
    LocalDateTime withHour(int i)
    LocalDateTime withDayOfMonth(int i)
    LocalDateTime withMonth(int i)
    LocalDateTime withYear(int i)

    如果有人给你了一个getTime()方法,这个方法的天总是不固定的,而这是一个错误,需要你将天定为每月的1号

    此时不能使用plus了,因为不固定,使用with直接修改即可

    public class Java8TimeDateDemo {
        public static void main(String[] args) {
            LocalDateTime time = getTime();
            LocalDateTime resultTime = time.withDayOfMonth(1);
            System.out.println("修改前: " + time);
            System.out.println("修改后: " + resultTime);
        }
    
        public static LocalDateTime getTime(){
            Random random = new Random();
            int day = random.nextInt(19);
            if (day == 0){
                day = 1;
            }
            return LocalDateTime.of(1999, 12, day, 12, 0);
        }
    }

    结果

    修改前: 1999-12-17T12:00
    修改后: 1999-12-01T12:00

     with(TemporalField, long newValue) 

    使用TemporalFiled实现类ChronoField

    第一个参数指定了修改的field

    public class Java8TimeDateDemo {
        public static void main(String[] args) {
            LocalDateTime time = getTime();
            LocalDateTime resultTime = time.with(ChronoField.DAY_OF_MONTH, 1); // 天改为1
            System.out.println("修改前: " + time);
            System.out.println("修改后: " + resultTime);
        }
    
        public static LocalDateTime getTime(){
            Random random = new Random();
            int day = random.nextInt(19);
            if (day == 0){
                day = 1;
            }
            return LocalDateTime.of(1999, 12, day, 12, 0);
        }
    }

    TemporalAdjuster与TemporalQuery

    可实现一些复杂操作

     with(TemporalAdjuster adjuster) 

    上面的参数是接口

    TemporalAdjusters类

    TemporalAdjuster是接口,该名字加了s后是个类

    static TemporalAdjuster dayOfWeekInMonth(int ordinal, DayOfWeek dayOfWeek)
    Returns the day-of-week in month adjuster, which returns a new date in the same month with the ordinal day-of-week.
    static TemporalAdjuster firstDayOfMonth()
    Returns the "first day of month" adjuster, which returns a new date set to the first day of the current month.
    static TemporalAdjuster firstDayOfNextMonth()
    Returns the "first day of next month" adjuster, which returns a new date set to the first day of the next month.
    static TemporalAdjuster firstDayOfNextYear()
    Returns the "first day of next year" adjuster, which returns a new date set to the first day of the next year.
    static TemporalAdjuster firstDayOfYear()
    Returns the "first day of year" adjuster, which returns a new date set to the first day of the current year.
    static TemporalAdjuster firstInMonth(DayOfWeek dayOfWeek)
    Returns the first in month adjuster, which returns a new date in the same month with the first matching day-of-week.
    static TemporalAdjuster lastDayOfMonth()
    Returns the "last day of month" adjuster, which returns a new date set to the last day of the current month.
    static TemporalAdjuster lastDayOfYear()
    Returns the "last day of year" adjuster, which returns a new date set to the last day of the current year.
    static TemporalAdjuster lastInMonth(DayOfWeek dayOfWeek)
    Returns the last in month adjuster, which returns a new date in the same month with the last matching day-of-week.
    static TemporalAdjuster next(DayOfWeek dayOfWeek)
    Returns the next day-of-week adjuster, which adjusts the date to the first occurrence of the specified day-of-week after the date being adjusted.
    static TemporalAdjuster nextOrSame(DayOfWeek dayOfWeek)
    Returns the next-or-same day-of-week adjuster, which adjusts the date to the first occurrence of the specified day-of-week after the date being adjusted unless it is already on that day in which case the same object is returned.
    static TemporalAdjuster ofDateAdjuster(UnaryOperator<LocalDate> dateBasedAdjuster)
    Obtains a TemporalAdjuster that wraps a date adjuster.
    static TemporalAdjuster previous(DayOfWeek dayOfWeek)
    Returns the previous day-of-week adjuster, which adjusts the date to the first occurrence of the specified day-of-week before the date being adjusted.
    static TemporalAdjuster previousOrSame(DayOfWeek dayOfWeek)
    Returns the previous-or-same day-of-week adjuster, which adjusts the date to the first occurrence of the specified day-of-week before the date being adjusted unless it is already on that day in which case the same object is returned.
    public class Java8TimeDateDemo {
        public static void main(String[] args) {
            LocalDate now = LocalDate.now();
    
            LocalDate nextMonth = now.with(TemporalAdjusters.firstDayOfNextMonth());
    
            System.out.println("修改前: " + now);
            System.out.println("修改后: " + nextMonth);
        }
    }

    DayOfWeek枚举类

    一周中星期几的枚举类

    enum DayOfWeek {
        SUNDAY("Sun"),
        MONDAY("Mon"),
        TUESDAY("Tue"),
        WEDNESDAY("Wed"),
        THURSDAY("Thu"),
        FRIDAY("Fri"),
        SATURDAY("Sat");
    
        private final String abbr;
    
        private DayOfWeek(String abbr) {
            this.abbr = abbr;
        }
    
        String getAbbr() {
            return abbr;
        }
    
        int value() {
            return ordinal() + 1;
        }
    }
    public class Java8TimeDateDemo {
        public static void main(String[] args) {
            LocalDate now = LocalDate.now();
            // 将当前时间修改为下一个周日
            LocalDate nextMonth = now.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
            System.out.println("修改前: " + now);
            System.out.println("修改后: " + nextMonth);
        }
    }

    自定义TemporalAdjuster调节器

    自定义日期时间的更改逻辑

    • 创建类实现接口TemporalAdjuster
    • 实现adjustInto()方法,传入一个日期的时间对象,完成逻辑后返回日期的时间对象
    • 通过with方法传入自定义调节器对象完成更改

    函数式接口

    有且仅有一个抽象方法的接口

    /**
     * 假如员工一个中领取工资,发薪日是每个月的15号,如果发薪日是周末,则调整为周五
     * 之后会传入一个日期的时间对象,判断日期时间对象是不是15号,如果不是15号改为15号,如果是周六或周日改为周五(上一个)
     */
    public class PayDayAdjuster implements TemporalAdjuster {
        
        public static void main(String[] args) {
            LocalDate payDay = LocalDate.of(2019, 12, 15);
            LocalDate realPayDay = LocalDate.from(new PayDayAdjuster().adjustInto(payDay));
            System.out.println("预计发薪日:" + payDay +" 真实发薪日: " + realPayDay);
        }
    
        @Override
        public Temporal adjustInto(Temporal temporal) {
    
            // 1.Temporal是日期时间类对象的父接口,实际上可以理解为传入的就是LocalDate或LocalTime对象,需要转换
            LocalDate payDay = LocalDate.from(temporal);
            // 2.判断当前封装的实际中的日期是不是当月15号,如果不是,则修改为15号
            int day;
            if (payDay.getDayOfMonth() != 15){
                day = 15;
            }else {
                day= payDay.getDayOfMonth();
            }
            LocalDate realPayDay = payDay.withDayOfMonth(day);
            // 3.判断realPayDay对象中封装的星期数是不是周六或周日,如果是改为上一个周五
            if (realPayDay.getDayOfWeek() == DayOfWeek.SUNDAY || realPayDay.getDayOfWeek() == DayOfWeek.SATURDAY){
                realPayDay =realPayDay.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));
            }
            return realPayDay;
        }
    }

    TemporalQuery的应用

    LocalDate和LocalTime都有一个方法叫query,可以针对日期进行查询。

     R query(Temporal query) 这个方法是一个泛型方法,返回的数据就是传入的泛型类的类型,TemporalQuery是一个泛型接口,里面有一个抽象方法是R queryFrom(TemporalAccessor temporal),TemporalAccessor是Temporal的父接口,实际就是LocalDate、LocalDateTime相关类的顶级父接口,这个qureyFrom方法的实现逻辑就是,传入一个日期/时间对象通过自定义逻辑返回数据。

    /**
     *   获取某一天距离下一个劳动节相隔天数
     **/
    public class UtilDayQueryImpl implements TemporalQuery<Long> {
    
        @Override
        public Long queryFrom(TemporalAccessor temporal) {
            // 1.TemporalAccessor是LocalDate和LocalDateTime的顶级父接口,相当于LocalDate就是其实现类,将temporal转换为LocalDate进行使用
            LocalDate now = LocalDate.from(temporal);
            // 2.封装当年的劳动节实际
            LocalDate labDay = LocalDate.of(now.getYear(), Month.MAY, 1);
            // 3.判断当前实际是否已经超过了劳动,超过了则labDay+1年
            if(now.isAfter(labDay)){
                labDay = labDay.plusYears(1);
            }
            // 4.通过ChronoUnit的between方法计算两个时间点的差额
            long days = ChronoUnit.DAYS.between(now, labDay);
            return days;
        }
    
        public static void main(String[] args) {
            LocalDate now = LocalDate.now();
            Long days = now.query(new UtilDayQueryImpl());
            System.out.println("当前的时间是: " + now + " ,距离下一个劳动节还有" + days + "天。");
        }
    }

    java.util.Date与java.time.LocalDate的转换

    可以使用Instant类作为中介,也可以使用java.sql.Date和java.sql.Timestamp类提供的方法进行转换

    使用Instant类

    Java8给Date类和Calender类提供了toInstant()方法,将它们转为LocalDate对象。

     public static void main(String[] args) {
            // 初始化Date对象
            Date date = new Date();
            // 1.将Date对象转换为Instant对象
            Instant instant = date.toInstant();
            // 2.Date类包含日期和时间信息,但没有时区信息,通过Instant的atZone方法添加时区信息
            ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
            // 3.将ZonedDateTime通过toLocalDateTime转换
            LocalDateTime localDateTime = zonedDateTime.toLocalDateTime();
            System.out.println("转换之前Date对象是: " + date);
            System.out.println("转换之后Date对象是: " + localDateTime);
        }

    使用java.sql.Date和java.sql.Timestamp类

    TimeStamp是时间戳对象,通过传入一个毫秒值对象进行初始化。

        public static void main(String[] args) {
            // 初始化java.sql.Date对象
            Date date = new Date(System.currentTimeMillis());
            // java.sql.Date类中自带转换为LocalDate的方法
            LocalDate localDate = date.toLocalDate();
            
            // 初始化java.sql.TimeStamp对象即时间戳对象
            // datetime
            Timestamp timeStamp =new Timestamp(System.currentTimeMillis());
            LocalDateTime localDate1 = timeStamp.toLocalDateTime();
        }

    由上可知

    可以将java.util.Date先转为java.sql.Date

    java.sql.Date的构造可以接收毫秒值,而java.util.Date对象的getTime方法可以获取毫秒值

        public static void main(String[] args) {
            java.util.Date date = new java.util.Date();
            // 初始化java.sql.Date对象
            java.sql.Date date1 = new Date(date.getTime());
            // java.sql.Date类中自带转换为LocalDate的方法
            LocalDate localDate = date1.toLocalDate();
            
        }

    Calender转为ZonedDateTime

        public static void main(String[] args) {
            // 1.初始化Calender对象
            Calendar cal = Calendar.getInstance();
            // 2.Calender获取时区对象
            TimeZone timeZone = cal.getTimeZone();
            // 3.获取ZoneId
            ZoneId zoneId = timeZone.toZoneId();
            // 4.ZoneDateTime有一个方法Instant,可以将一个Instant对象和ZoneId对象封装为一个ZonedDate对象
            ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(cal.toInstant(), zoneId);
            System.out.println(zonedDateTime);
        }

    Calender转为LocalDateTime

    Calender可以得到年月日时分秒的信息,这些信息可以作为LocalDateTime构造方法的参数

        public static void main(String[] args) {
            // 1.初始化Calender对象
            Calendar cal = Calendar.getInstance();
            // 2.通过get方法获得Calender对象中的信息
            int year = cal.get(Calendar.YEAR);
            int month = cal.get(Calendar.MONTH);
            int day = cal.get(Calendar.DAY_OF_MONTH);
            int hour = cal.get(Calendar.HOUR);
            int minute = cal.get(Calendar.MINUTE);
            int second = cal.get(Calendar.SECOND);
            // 3.将以上方法获得的参数作为参数 month从0开始,下面的month要加1
            LocalDateTime localDateTime = LocalDateTime.of(year, month+1, day, hour, minute ,second);
            System.out.println(localDateTime);
        }

    日期的解析与格式化

    SimpleDateFormat类是线程不安全的,Java8提供了新类DateTimeFormatter

    DateTimeFormatter提供了大量的预定义格式化器,包括常量和模式字母以及本地化样式。

    parse/format

    通过时间日期对象的parse/format方法可以直接进行转换

     public static void main(String[] args) {
            // 初始化
            LocalDateTime now = LocalDateTime.now();
    
            // now()可以直接调用format方法进行格式化
            String s1 = now.format(DateTimeFormatter.ISO_DATE_TIME);
            String s2 = now.format(DateTimeFormatter.ISO_DATE);
            System.out.println(s1);
            System.out.println(s2);
            // 解析字符串。
            LocalDateTime time = LocalDateTime.parse(s1);
            System.out.println(time);
        }

    结果

    2020-09-17T14:45:32.553
    2020-09-17
    2020-09-17T14:45:32.553

    ofLocalizedDate方法

        public static void main(String[] args) {
            // 初始化
            LocalDateTime now = LocalDateTime.now();
    
            // now()可以直接调用format方法进行格式化
            String s1 = now.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL));
            String s2 = now.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG));
            String s3 = now.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM));
            String s4 = now.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT));
    
            System.out.println(s1);
            System.out.println(s2);
            System.out.println(s3);
            System.out.println(s4);
        }

    结果

    2020年9月17日 星期四
    2020年9月17日
    2020-9-17
    20-9-17

    不同时区显示方式不一样,在其他时区可能不显示中文,根据系统默认时区

    自定义格式化

    可以通过DateTimeFormatter类提供的ofPattern方式创建自定义格式化器,格式化的写法与SimpleDateFormat相同。

      public static void main(String[] args) {
            // 初始化
            LocalDateTime now = LocalDateTime.now();
            String dt = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm-ss"));
            System.out.println(dt);
        }

    结果

    2020-09-17 14:54-13

    总结

    小项目-万年历

  • 相关阅读:
    Yii2安装任务调度扩展
    分享书籍[writing idiomatic python ebook]
    python待解决问题笔记
    dojo使用笔记: 自定义ConfirmDialog
    dojo使用疑难杂症集锦
    学习"大众点评网的架构设计与实践"
    一个前端html模板处理引擎(javascript)
    日历设计之重复事件规则设计
    TCP/IP之TCP的建立与终止
    python正则表达式
  • 原文地址:https://www.cnblogs.com/aidata/p/13685231.html
Copyright © 2020-2023  润新知