Java8新特性二

Java8新特性二

了解Fork/Join框架

Fork/Join框架:就是在必要的情况下,将一个大任务进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个小任务的结果进行join汇总。
在这里插入图片描述

Fork/Join框架与线程池的区别

采用“工作窃取”模式
当执行新的任务时,它可以将其拆分成更小的任务执行,并将小任务添加到线程队列中,当一个线程在执行任务时获取不到时,从一个随机的线程队列末尾偷一个并把它放在自己的队列中。

import java.util.concurrent.RecursiveTask;

//RecursiveTask有返回值
//RecursiveAcation没有返回值
//Recursive是递归的意思
public class ForkJoinCalculate extends RecursiveTask<Long> {

    private long start;
    private long end;
    private final long THRESHOLD = 10000;

    public ForkJoinCalculate(long start, long end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        long len = end -start;
        if(len<=THRESHOLD)
        {
            long sum = 0;
            for(long i = start;i<=end;i++)
            {
                sum+=i;
            }
            return sum;
        }
        else
        {
            long middle = (start+end)/2;
            ForkJoinCalculate left = new ForkJoinCalculate(start,middle);
            left.fork();//拆分子任务,同时压入线程队列

            ForkJoinCalculate right = new ForkJoinCalculate(middle+1,end);
            right.fork();
            return left.join()+right.join();
        }

    }
}

import org.junit.Test;

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;

/**
 * @ClassName TestForkJoin
 * @Description: TODO
 * @Author renjie
 * @Date 2021/5/20
 **/
public class TestForkJoin {

    @Test
    public void test()
    {
        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinTask<Long> task = new ForkJoinCalculate(0,100000000L);
        Long sum = pool.invoke(task);
        System.out.println(sum);

    }
}

Java8并行流

import org.junit.Test;

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;

/**
 * @ClassName TestForkJoin
 * @Description: TODO
 * @Author renjie
 * @Date 2021/5/20
 **/
public class TestForkJoin {
    /**
     * Java8并行流
     */
    @Test
    public void test1()
    {
        Instant start = Instant.now();
        //串行流
        LongStream.rangeClosed(0,100000000000L)
                .reduce(0,Long::sum);
        Instant end = Instant.now();
        System.out.println("串行流耗费时间为:"+ Duration.between(start,end).toMillis());


        start = Instant.now();
        //并行流
        LongStream.rangeClosed(0,100000000000L)
                .parallel()
                .reduce(0,Long::sum);
        end = Instant.now();
        System.out.println("并行流耗费时间为:"+ Duration.between(start,end).toMillis());

    }
}

输出

串行流耗费时间为:38956
并行流耗费时间为:13387

Optional类

Optional容器类的常用方法:

  • Optional.of(T t):创建一个Optional实例
  • Optional.empty():创建一个空的Optional实例
  • Optional.ofNullable(T t):若t不为null,创建Optional实例,否则创建空实例
  • isPresent():判断是否包含值
  • orElse(T t):如果调用对象包含值,返回该值,否则返回s获取的值。
  • map(Function f):如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
  • flatMap(Function mapper):与map类似,要求返回值必须是Optional

示例

public class TestOptional {

    @Test
    public void test()
    {
        Optional<Employee> op = Optional.of(new Employee());
        Employee emp = op.get();
        System.out.println(emp);
    }
}

结果

Employee{name='null', age=0, salary=0.0, status=null}

例子2

public class TestOptional {
    @Test
    public void test1()
    {
        Optional<Object> empty = Optional.empty();
        System.out.println(empty.get());
    }
}

结果:抛出异常

java.util.NoSuchElementException: No value present

例子3

public class TestOptional {
	@Test
    public void test1()
    {
        Optional<Object> empty = Optional.empty();
        //判断是否包含值
        if(empty.isPresent())
        {
        	System.out.println(empty.get());
        }
        else
        	System.out.println("啥都没有");
    }
}

输出

啥都没有

例子4

有则获取,没有则替换

public class TestOptional {
    @Test
    public void test3()
    {
        Optional<Employee> op = Optional.ofNullable(new Employee());
        Employee employee = op.orElse(new Employee("sss",20,1111.11,Employee.Status.BUSY));
        System.out.println(employee);
    }
}

输出

Employee{name='null', age=0, salary=0.0, status=null}

例子5

public class TestOptional {
    @Test
    public void test4()
    {
        Optional<Employee> op = Optional.ofNullable(new Employee("sss",20,1111.11,Employee.Status.BUSY));
        Optional<String> str = op.map(Employee::getName);
        System.out.println(str.get());
    }
}

输出

sss

例子6

flatMap返回的必须是Optional 进一步避免空指针异常。

public class TestOptional {
    @Test
    public void test5()
    {
        Optional<Employee> op = Optional.ofNullable(new Employee("sss",20,1111.11,Employee.Status.BUSY));
        Optional<String> str = op.flatMap((e)->Optional.of(e.getName()));
        System.out.println(str.get());
    }
}

输出

sss

例子7

class NewMan {
    private Optional<Godness> godness = Optional.empty();

    public NewMan() {
    }

    @Override
    public String toString() {
        return "NewMan{" +
                "godness=" + godness +
                '}';
    }

    public Optional<Godness> getGodness() {
        return godness;
    }

    public void setGodness(Optional<Godness> godness) {
        this.godness = godness;
    }

    public NewMan(Optional<Godness> godness) {
        this.godness = godness;
    }
}

public class TestOptional {
    @Test
    public void test6()
    {
        Optional<NewMan> op = Optional.ofNullable(null);
        String str = getGodnessName(op);
        System.out.println(str);

    }

    private String getGodnessName(Optional<NewMan> man) {
        return man.orElse(new NewMan())
                .getGodness()
                .orElse(new Godness("Miss Li"))
                .getName();
    }

}

输出

Miss Li

接口中的默认方法与静态方法

以前接口中只可以有全局静态常量和抽象方法。
现在还可以有默认方法。使用default修饰符。

java8中允许接口包含具有具体实现的方法,该方法称为“默认方法”,默认方法使用default关键词修饰。

也允许包含静态方法

例如:

public interface MyFunc<T> {

    T MyFunc(int a);
    default String getName()
    {
        return "hello java8";
    }
    static int getAge()
    {
    	return 18;
    }
}

接口默认方法的“类优先”原则

若一个接口中定义了一个默认方法,而另外一个父类或接口中又定义了一个同名的方法时。

  • 选择父类中的方法。如果一个父类提供了一个具体的实现,那么接口中具有相同名称和参数的默认方法会被忽略。
  • 接口冲突,如果一个父接口提供了一个默认方法,而另一个接口也提供了一个具有相同名称和参数列表的方法(不管方法是否是默认),那么必须覆盖该方法来解决冲突。

新时间API

之前的时间相关的类:

  • Date
  • Calendar:每周第一天默认从星期日开始,是可变的,线程不安全,格式化日期用SimpleDateFormat

新的时间API
不可变,不管怎么变都会产生新的实例。

  • 1、java.time下面的众多类,如LocalDate、LocalTime等,时间戳Instant
  • 2、时间日期格式化,java.time.format包下的类

旧API中SimpleDateFormat存在的线程安全问题

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;

/**
 * @ClassName TestSimpleDateFormat
 * @Description: TODO
 * @Author renjie
 * @Date 2021/5/22
 **/
public class TestSimpleDateFormat {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Callable<Date> task = new Callable<Date>() {
            @Override
            public Date call() throws Exception {
                return sdf.parse("20161218");
            }
        };
        ExecutorService pool = Executors.newFixedThreadPool(10);

        List<Future<Date>> result = new ArrayList<>();
        for (int i = 0 ;i<10;i++) {

            result.add(pool.submit(task));
        }

        for(Future<Date> future:result)
        {
            System.out.println(future.get());
        }
    }
}

结果

Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.NumberFormatException: multiple points
	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at TestSimpleDateFormat.main(TestSimpleDateFormat.java:32)
Caused by: java.lang.NumberFormatException: multiple points

java.lang.NumberFormatException: multiple points问题
一般这种问题主要是因为SimpleDateFormat在多线程环境下,是线程不安全的,所以如果你在多线程环境中共享了SimpleDateFormat的实例,比如你在类似日期类中定义了一个全局的SimpleDateFormat对象,这样子肯定会出现上述的报错。

使用ThreadLocal进行改进
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;

class DateFormatThreadLocal {
    public static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>(){
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyyMMdd");
        }
    };
    public static Date convert(String source) throws ParseException {
        return df.get().parse(source);
    }
}

public class TestDateFormatThreadLocal {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<Date> task = new Callable<Date>() {
            @Override
            public Date call() throws Exception {
                return DateFormatThreadLocal.convert("20161218");
            }
        };
        ExecutorService pool = Executors.newFixedThreadPool(10);

        List<Future<Date>> result = new ArrayList<>();
        for (int i = 0 ;i<10;i++) {

            result.add(pool.submit(task));
        }

        for(Future<Date> future:result)
        {
            System.out.println(future.get());
        }

        pool.shutdown();
    }
}

输出

Sun Dec 18 00:00:00 CST 2016
Sun Dec 18 00:00:00 CST 2016
Sun Dec 18 00:00:00 CST 2016
Sun Dec 18 00:00:00 CST 2016
Sun Dec 18 00:00:00 CST 2016
Sun Dec 18 00:00:00 CST 2016
Sun Dec 18 00:00:00 CST 2016
Sun Dec 18 00:00:00 CST 2016
Sun Dec 18 00:00:00 CST 2016
Sun Dec 18 00:00:00 CST 2016

新时间日期API

LocalDate、LocalTime、LocalDateTime

使用LocalDate、LocalTime、LocalDateTime

  • LocalDate、LocalTime、LocalDateTime类的实例是不可变的对象,分别表示使用ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。

注:ISO-8601日历系统说国际标准化组织制定的现代公民的日期和时间的表示法。

import org.junit.Test;

import java.time.LocalDateTime;

/**
 * @ClassName TestLocalDateTime
 * @Description: TODO
 * @Author renjie
 * @Date 2021/5/22
 **/
public class TestLocalDateTime {

    @Test
    public void test()
    {
        LocalDateTime ldt = LocalDateTime.now();
        System.out.println(ldt);

        LocalDateTime ldt2 = LocalDateTime.of(2021,5,22,14,20,16);
        System.out.println(ldt2);

        LocalDateTime ldt3 = ldt2.plusYears(2);
        System.out.println(ldt3);
        LocalDateTime ldt4 = ldt3.minusMonths(2);
        System.out.println(ldt4);

        System.out.println(ldt4.getYear());
        System.out.println(ldt4.getMonthValue());
        System.out.println(ldt4.getDayOfMonth());
        System.out.println(ldt4.getHour());
        System.out.println(ldt4.getMinute());
        System.out.println(ldt4.getSecond());
        

    }

}

从上面可以看出,不管做什么样的改变都会拿到一个新的实例。

输出

2021-05-22T14:41:39.915
2021-05-22T14:20:16
2023-05-22T14:20:16
2023-03-22T14:20:16
2023
3
22
14
20
16

Instant:时间戳

以Unix元年:1970年1月1日00:00:00到某个时间之间的毫秒值。

import org.junit.Test;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;

/**
 * @ClassName TestLocalDateTime
 * @Description: TODO
 * @Author renjie
 * @Date 2021/5/22
 **/
public class TestLocalDateTime {

    @Test
    public void test2()
    {
        Instant ins1 = Instant.now(); //默认获取UTC时区
        System.out.println(ins1);
        //将日期格式转换成时间戳格式
        System.out.println(ins1.toEpochMilli());

        //带偏移量的时间日期
        OffsetDateTime odt = ins1.atOffset(ZoneOffset.ofHours(2));
        System.out.println(odt);

        //将秒转换为日期格式
        Instant instant = Instant.ofEpochSecond(61);
        System.out.println(instant);
    }

}

输出

2021-05-22T06:57:26.394Z
1621666646394
2021-05-22T08:57:26.394+02:00
1970-01-01T00:01:01Z

计算时间间隔、日期间隔

Duration:计算两个"时间"之间的间隔
public class TestLocalDateTime {
@Test
    public void test4()
    {
        //默认获取etc时区
        Instant ins1 = Instant.now();

        try {
            Thread.sleep(1000);
        }
        catch (Exception e)
        {
        }
        Instant ins2 = Instant.now();
        Duration between = Duration.between(ins1, ins2);
        System.out.println(between.toMillis());
    }
}

输出

1003

Period:计算两个日期之间的间隔

import org.junit.Test;

import java.time.*;
public class TestLocalDateTime {

    @Test
    public void test5()
    {
        LocalDate ld1 = LocalDate.of(2015,1,1);
        LocalDate ld2 = LocalDate.now();
        Period period = Period.between(ld1,ld2);
        //P6Y4M21D表示period 1Year 4Month 21Day
        System.out.println(period);
        System.out.println(period.getYears());
        System.out.println(period.getMonths());
        System.out.println(period.getDays());
    }
}

输出

P6Y4M21D
6
4
21

日期操作TemporalAdjusters

  • TemporalAdjuster:时间矫正器,有时我们可能获取例如:将日期调整到“下个周日”等操作
  • TemporalAdjusters:该类通过静态方法提供了大量的常用TemporalAdjuster的实现
import org.junit.Test;

import java.time.*;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;

public class TestLocalDateTime {
    //时间矫正器
    @Test
    public void test6()
    {
        LocalDateTime ldt = LocalDateTime.now();
        System.out.println(ldt);
        //将日期指定成10号
        LocalDateTime ldt2 = ldt.withDayOfMonth(10);
        System.out.println(ldt2);
        //将日期修改为下一个sunday
        LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
        System.out.println(ldt3);

        //自定义:下一个工作日
        LocalDateTime ldt5 = ldt.with(l->
        {
            LocalDateTime ldt4 = (LocalDateTime) l;
            DayOfWeek dow = ldt4.getDayOfWeek();
            if(dow.equals(DayOfWeek.FRIDAY))
                return ldt4.plusDays(3);
            else if(dow.equals(DayOfWeek.SATURDAY))
                return ldt4.plusDays(2);
            else
                return ldt4.plusDays(1);
        });
        System.out.println(ldt5);

    }

}


格式化时间/日期:DateTimeFormatter

public class TestLocalDateTime {
    //DateTimeFormatter:格式化时间/日期
    @Test
    public void test7()
    {
        DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE;
        LocalDateTime ldt = LocalDateTime.now();
        System.out.println(ldt);
        String format = ldt.format(dtf);
        System.out.println(format);
        
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
        String format2 = ldt.format(dtf2);
        System.out.println(format2);
        
        //将字符串转换为LocalDateTime
        LocalDateTime res = ldt.parse(format2,dtf2);
        System.out.println(res);
    }

}

输出

2021-05-22T16:11:58.470
2021-05-22
2021052216:11:58
2021-05-22T16:11:58

时区的处理

public class TestLocalDateTime {
    @Test
    public void test8()
    {
        Set<String> set = ZoneId.getAvailableZoneIds();
        set.forEach(System.out::print);
    }
}

输出

Asia/AdenAmerica/CuiabaEtc/GMT+9Etc/GMT+8Africa/NairobiAmerica/MarigotAsia/AqtauPacific/KwajaleinAmerica/El_SalvadorAsia/PontianakAfrica/CairoPacific/Pago_PagoAfrica/MbabaneAsia/KuchingPacific/HonoluluPacific/RarotongaAmerica/GuatemalaAustralia/HobartEurope/LondonAmerica/BelizeAmerica/PanamaAsia/ChungkingAmerica/ManaguaAmerica/Indiana/PetersburgAsia/YerevanEurope/BrusselsGMTEurope/WarsawAmerica/ChicagoAsia/KashgarChile/ContinentalPacific/YapCETEtc/GMT-1Etc/GMT-0Europe/JerseyAmerica/TegucigalpaEtc/GMT-5Europe/IstanbulAmerica/EirunepeEtc/GMT-4America/MiquelonEtc/GMT-3Europe/LuxembourgEtc/GMT-2Etc/GMT-9America/Argentina/CatamarcaEtc/GMT-8Etc/GMT-7Etc/GMT-6Europe/ZaporozhyeCanada/YukonCanada/AtlanticAtlantic/St_HelenaAustralia/TasmaniaLibyaEurope/GuernseyAmerica/Grand_TurkUS/Pacific-NewAsia/SamarkandAmerica/Argentina/CordobaAsia/Phnom_PenhAfrica/KigaliAsia/AlmatyUS/AlaskaAsia/DubaiEurope/Isle_of_ManAmerica/AraguainaCubaAsia/NovosibirskAmerica/Argentina/SaltaEtc/GMT+3Africa/TunisEtc/GMT+2Etc/GMT+1Pacific/FakaofoAfrica/TripoliEtc/GMT+0IsraelAfrica/BanjulEtc/GMT+7Indian/ComoroEtc/GMT+6Etc/GMT+5Etc/GMT+4Pacific/Port_MoresbyUS/ArizonaAntarctica/SyowaIndian/ReunionPacific/PalauEurope/KaliningradAmerica/MontevideoAfrica/WindhoekAsia/KarachiAfrica/MogadishuAustralia/PerthBrazil/EastEtc/GMTAsia/ChitaPacific/EasterAntarctica/DavisAntarctica/McMurdoAsia/MacaoAmerica/ManausAfrica/FreetownEurope/BucharestAsia/TomskAmerica/Argentina/MendozaAsia/MacauEurope/MaltaMexico/BajaSurPacific/TahitiAfrica/AsmeraEurope/BusingenAmerica/Argentina/Rio_GallegosAfrica/MalaboEurope/SkopjeAmerica/CatamarcaAmerica/GodthabEurope/SarajevoAustralia/ACTGB-EireAfrica/LagosAmerica/CordobaEurope/RomeAsia/DaccaIndian/MauritiusPacific/SamoaAmerica/ReginaAmerica/Fort_WayneAmerica/Dawson_CreekAfrica/AlgiersEurope/MariehamnAmerica/St_JohnsAmerica/St_ThomasEurope/ZurichAmerica/AnguillaAsia/DiliAmerica/DenverAfrica/BamakoEurope/SaratovGBMexico/GeneralPacific/WallisEurope/GibraltarAfrica/ConakryAfrica/LubumbashiAsia/IstanbulAmerica/HavanaNZ-CHATAsia/ChoibalsanAmerica/Porto_AcreAsia/OmskEurope/VaduzUS/MichiganAsia/DhakaAmerica/BarbadosEurope/TiraspolAtlantic/Cape_VerdeAsia/YekaterinburgAmerica/LouisvillePacific/JohnstonPacific/ChathamEurope/LjubljanaAmerica/Sao_PauloAsia/JayapuraAmerica/CuracaoAsia/DushanbeAmerica/GuyanaAmerica/GuayaquilAmerica/MartiniquePortugalEurope/BerlinEurope/MoscowEurope/ChisinauAmerica/Puerto_RicoAmerica/Rankin_InletPacific/PonapeEurope/StockholmEurope/BudapestAmerica/Argentina/JujuyAustralia/EuclaAsia/ShanghaiUniversalEurope/ZagrebAmerica/Port_of_SpainEurope/HelsinkiAsia/BeirutAsia/Tel_AvivPacific/BougainvilleUS/CentralAfrica/Sao_TomeIndian/ChagosAmerica/CayenneAsia/YakutskPacific/GalapagosAustralia/NorthEurope/ParisAfrica/NdjamenaPacific/FijiAmerica/Rainy_RiverIndian/MaldivesAustralia/YancowinnaSystemV/AST4Asia/OralAmerica/YellowknifePacific/EnderburyAmerica/JuneauAustralia/VictoriaAmerica/Indiana/VevayAsia/TashkentAsia/JakartaAfrica/CeutaAsia/BarnaulAmerica/RecifeAmerica/Buenos_AiresAmerica/NoronhaAmerica/Swift_CurrentAustralia/AdelaideAmerica/MetlakatlaAfrica/DjiboutiAmerica/ParamariboEurope/SimferopolEurope/SofiaAfrica/NouakchottEurope/PragueAmerica/Indiana/VincennesAntarctica/MawsonAmerica/KralendijkAntarctica/TrollEurope/SamaraIndian/ChristmasAmerica/AntiguaPacific/GambierAmerica/IndianapolisAmerica/InuvikAmerica/IqaluitPacific/FunafutiUTCAntarctica/MacquarieCanada/PacificAmerica/MonctonAfrica/GaboronePacific/ChuukAsia/PyongyangAmerica/St_VincentAsia/GazaEtc/UniversalPST8PDTAtlantic/FaeroeAsia/QyzylordaCanada/NewfoundlandAmerica/Kentucky/LouisvilleAmerica/YakutatAsia/Ho_Chi_MinhAntarctica/CaseyEurope/CopenhagenAfrica/AsmaraAtlantic/AzoresEurope/ViennaROKPacific/PitcairnAmerica/MazatlanAustralia/QueenslandPacific/NauruEurope/TiraneAsia/KolkataSystemV/MST7Australia/CanberraMETAustralia/Broken_HillEurope/RigaAmerica/DominicaAfrica/AbidjanAmerica/MendozaAmerica/SantaremKwajaleinAmerica/AsuncionAsia/Ulan_BatorNZAmerica/BoiseAustralia/CurrieEST5EDTPacific/GuamPacific/WakeAtlantic/BermudaAmerica/Costa_RicaAmerica/DawsonAsia/ChongqingEireEurope/AmsterdamAmerica/Indiana/KnoxAmerica/North_Dakota/BeulahAfrica/AccraAtlantic/FaroeMexico/BajaNorteAmerica/MaceioEtc/UCTPacific/ApiaGMT0America/AtkaPacific/NiueAustralia/Lord_HoweEurope/DublinPacific/TrukMST7MDTAmerica/MonterreyAmerica/NassauAmerica/JamaicaAsia/BishkekAmerica/AtikokanAtlantic/StanleyAustralia/NSWUS/HawaiiSystemV/CST6Indian/MaheAsia/AqtobeAmerica/SitkaAsia/VladivostokAfrica/LibrevilleAfrica/MaputoZuluAmerica/Kentucky/MonticelloAfrica/El_AaiunAfrica/OuagadougouAmerica/Coral_HarbourPacific/MarquesasBrazil/WestAmerica/ArubaAmerica/North_Dakota/CenterAmerica/CaymanAsia/UlaanbaatarAsia/BaghdadEurope/San_MarinoAmerica/Indiana/Tell_CityAmerica/TijuanaPacific/SaipanSystemV/YST9Africa/DoualaAmerica/ChihuahuaAmerica/OjinagaAsia/HovdAmerica/AnchorageChile/EasterIslandAmerica/HalifaxAntarctica/RotheraAmerica/Indiana/IndianapolisUS/MountainAsia/DamascusAmerica/Argentina/San_LuisAmerica/SantiagoAsia/BakuAmerica/Argentina/UshuaiaAtlantic/ReykjavikAfrica/BrazzavilleAfrica/Porto-NovoAmerica/La_PazAntarctica/DumontDUrvilleAsia/TaipeiAntarctica/South_PoleAsia/ManilaAsia/BangkokAfrica/Dar_es_SalaamPolandAtlantic/MadeiraAntarctica/PalmerAmerica/Thunder_BayAfrica/Addis_AbabaAsia/YangonEurope/UzhgorodBrazil/DeNoronhaAsia/AshkhabadEtc/ZuluAmerica/Indiana/MarengoAmerica/CrestonAmerica/Punta_ArenasAmerica/Mexico_CityAntarctica/VostokAsia/JerusalemEurope/AndorraUS/SamoaPRCAsia/VientianePacific/KiritimatiAmerica/MatamorosAmerica/Blanc-SablonAsia/RiyadhIcelandPacific/PohnpeiAsia/Ujung_PandangAtlantic/South_GeorgiaEurope/LisbonAsia/HarbinEurope/OsloAsia/NovokuznetskCST6CDTAtlantic/CanaryAmerica/Knox_INAsia/KuwaitSystemV/HST10Pacific/EfateAfrica/LomeAmerica/BogotaAmerica/MenomineeAmerica/AdakPacific/NorfolkEurope/KirovAmerica/ResolutePacific/TarawaAfrica/KampalaAsia/KrasnoyarskGreenwichSystemV/EST5America/EdmontonEurope/PodgoricaAustralia/SouthCanada/CentralAfrica/BujumburaAmerica/Santo_DomingoUS/EasternEurope/MinskPacific/AucklandAfrica/CasablancaAmerica/Glace_BayCanada/EasternAsia/QatarEurope/KievSingaporeAsia/MagadanSystemV/PST8America/Port-au-PrinceEurope/BelfastAmerica/St_BarthelemyAsia/AshgabatAfrica/LuandaAmerica/NipigonAtlantic/Jan_MayenBrazil/AcreAsia/MuscatAsia/BahrainEurope/VilniusAmerica/FortalezaEtc/GMT0US/East-IndianaAmerica/HermosilloAmerica/CancunAfrica/MaseruPacific/KosraeAfrica/KinshasaAsia/KathmanduAsia/SeoulAustralia/SydneyAmerica/LimaAustralia/LHIAmerica/St_LuciaEurope/MadridAmerica/Bahia_BanderasAmerica/MontserratAsia/BruneiAmerica/Santa_IsabelCanada/MountainAmerica/Cambridge_BayAsia/ColomboAustralia/WestIndian/AntananarivoAustralia/BrisbaneIndian/MayotteUS/Indiana-StarkeAsia/UrumqiUS/AleutianEurope/VolgogradAmerica/Lower_PrincesAmerica/VancouverAfrica/BlantyreAmerica/Rio_BrancoAmerica/DanmarkshavnAmerica/DetroitAmerica/ThuleAfrica/LusakaAsia/Hong_KongIranAmerica/Argentina/La_RiojaAfrica/DakarSystemV/CST6CDTAmerica/TortolaAmerica/Porto_VelhoAsia/SakhalinEtc/GMT+10America/ScoresbysundAsia/KamchatkaAsia/ThimbuAfrica/HarareEtc/GMT+12Etc/GMT+11NavajoAmerica/NomeEurope/TallinnTurkeyAfrica/KhartoumAfrica/JohannesburgAfrica/BanguiEurope/BelgradeJamaicaAfrica/BissauAsia/TehranWETEurope/AstrakhanAfrica/JubaAmerica/Campo_GrandeAmerica/BelemEtc/GreenwichAsia/SaigonAmerica/EnsenadaPacific/MidwayAmerica/JujuyAfrica/TimbuktuAmerica/BahiaAmerica/Goose_BayAmerica/VirginAmerica/PangnirtungAsia/KatmanduAmerica/PhoenixAfrica/NiameyAmerica/WhitehorsePacific/NoumeaAsia/TbilisiAmerica/MontrealAsia/MakassarAmerica/Argentina/San_JuanHongkongUCTAsia/NicosiaAmerica/Indiana/WinamacSystemV/MST7MDTAmerica/Argentina/ComodRivadaviaAmerica/Boa_VistaAmerica/GrenadaAsia/AtyrauAustralia/DarwinAsia/KhandygaAsia/Kuala_LumpurAsia/FamagustaAsia/ThimphuAsia/RangoonEurope/BratislavaAsia/CalcuttaAmerica/Argentina/TucumanAsia/KabulIndian/CocosJapanPacific/TongatapuAmerica/New_YorkEtc/GMT-12Etc/GMT-11Etc/GMT-10SystemV/YST9YDTEurope/UlyanovskEtc/GMT-14Etc/GMT-13W-SUAmerica/MeridaEETAmerica/RosarioCanada/SaskatchewanAmerica/St_KittsArctic/LongyearbyenAmerica/Fort_NelsonAmerica/CaracasAmerica/GuadeloupeAsia/HebronIndian/KerguelenSystemV/PST8PDTAfrica/MonroviaAsia/Ust-NeraEgyptAsia/SrednekolymskAmerica/North_Dakota/New_SalemAsia/AnadyrAustralia/MelbourneAsia/IrkutskAmerica/ShiprockAmerica/WinnipegEurope/VaticanAsia/AmmanEtc/UTCSystemV/AST4ADTAsia/TokyoAmerica/TorontoAsia/SingaporeAustralia/LindemanAmerica/Los_AngelesSystemV/EST5EDTPacific/MajuroAmerica/Argentina/Buenos_AiresEurope/NicosiaPacific/GuadalcanalEurope/AthensUS/PacificEurope/Monaco

修改时区

public class TestLocalDateTime {
    @Test
    public void test9()
    {
        LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Europe/Tallinn"));
        System.out.println(ldt);

        LocalDateTime ldt2 = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
        ZonedDateTime zdt = ldt2.atZone(ZoneId.of("Asia/Shanghai"));
        System.out.println(zdt);
    }
}

输出

2021-05-22T11:28:21.787
2021-05-22T16:28:21.795+08:00[Asia/Shanghai]

+08:00表示与UTC有8小时的时差

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值