时区设置

说明

一般研发中可能涉及的时区:数据库、代码中。

咱们所在时区为东八区,而默认时区为0区,差距八个小时,所以每次在与数据库交互时就会发生八小时的误差,

jdbc:mysql://localhost:3306/friend?useSSL=false&serverTimezone=Asia/Shanghai

 

1. 数据库

jdbc连接时可通过serverTimezone=UTC设置jdbc:mysql://59.110.137.112:3306/answer?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=UTC&nullCatalogMeansCurrent=true

 

创建表时或添加字段时指定默认时间(不建议)。推荐代码传参入库

 

 

mysql涉及的日期和时间的数据类型是datetime、timestamp

在MySQL中,datetime和timestamp是两种用于存储日期和时间的数据类型。

  1. datetime数据类型:datetime存储了一个特定的日期和时间,范围从'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。它使用8个字节来存储,并且不受时区影响。当您插入或查询datetime值时,它将以原样存储和检索。

  2. timestamp数据类型:timestamp也存储了一个特定的日期和时间,范围从'1970-01-01 00:00:01' UTC到'2038-01-19 03:14:07' UTC。它使用4个字节来存储,并且受时区设置的影响。当您插入或查询timestamp值时,它将自动转换为与时区相对应的UTC值存储,并在检索时再次转换为本地时区。

关键区别:

  • datetime的范围更大,而timestamp受限于2038年问题。
  • datetime不受时区影响,而timestamp受时区设置的影响。
  • datetime使用8个字节存储,而timestamp使用4个字节存储。

根据您的需求,选择适合的数据类型。如果您需要存储可随时更改的事件(例如记录修改时间),可以使用timestamp。如果您需要存储某个固定时间的特定日期和时间,则可以使用datetime。

在选择使用datetimetimestamp类型时,可以根据以下几个方面进行考虑:

  1. 存储范围:datetime的存储范围为'1000-01-01 00:00:00'到'9999-12-31 23:59:59',而timestamp的存储范围为'1970-01-01 00:00:01'到'2038-01-19 03:14:07'。如果你需要存储更早或更远的日期和时间,应选择datetime类型。

  2. 存储精度:datetime类型具有毫秒级别的精度,而timestamp类型只能精确到秒。如果需要更高的精度,应选择datetime类型。

  3. 时区处理:datetime类型不会自动进行时区转换,存储的值是按照数据库服务器的时区来解释的。而timestamp类型会自动进行时区转换,存储的值会按照当前会话的时区来解释。因此,在涉及跨时区查询和排序时,timestamp类型可能更适合。

最佳实践示例:

CREATE TABLE example (
    id INT,
    created_at DATETIME,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

 

实际上大厂不建议使用数据库默认值,而采用传参入库。

在上述示例中,created_at字段使用了datetime类型,用于记录创建时间。updated_at字段使用了timestamp类型,并设置了默认值为当前时间,并在更新时自动更新为当前时间,用于记录更新时间。这样可以方便地跟踪记录的创建和更新时间。

2. 代码

方法一:JVM运行时增加参数,指定时区 -Duser.timezone=UTC

方法二:直接在程序中设置时区。System.setProperty(“user.timezone”,”UTC″);

Java涉及日期、时间类:

1. java.util.Date:包含日期和时间,老牌类,一般与java.util.Calendar结合使用,实现日期、时间的即使)

2. java.time.LocalDate:只表示日期

3. java.time.LocalDateTime:表示日期和时间

4.java.time.LocalTime:表示时间

java.time.LocalDate

java.time.LocalDate是Java 8新增的日期类,用于表示年月日的日期。

特点:

  1. LocalDate是不可变的类,可以确保线程安全;
  2. LocalDate的实例不能修改,只能通过with方法创建一个新的对象;
  3. LocalDate是final类型且有多个静态工厂方法创建;
  4. LocalDate是值类型,可以通过isEqual比较两个LocalDate是否相等;
  5. LocalDate的格式是yyyy-MM-dd,可以通过toString、format方法进行格式化输出。

 

Java.time.LocalDate是Java 8中的日期类,用于表示日期。它提供了丰富的方法来操纵和获取日期信息。

以下是一些常见的用法和示例:

  1. 创建 LocalDate 对象:

    • 使用 now() 方法获取当前日期:LocalDate.now()
    • 使用 of() 方法创建指定日期:LocalDate.of(2022, 10, 1)
  2. 获取日期信息:

    • 获取年份:localDate.getYear()
    • 获取月份:localDate.getMonthValue()
    • 获取日:localDate.getDayOfMonth()
    • 获取星期几:localDate.getDayOfWeek()
  3. 比较日期:

    • 判断两个日期是否相等:localDate1.equals(localDate2)
    • 判断日期1是否在日期2之前:localDate1.isBefore(localDate2)
    • 判断日期1是否在日期2之后:localDate1.isAfter(localDate2)
  4. 操纵日期:

    • 增加天数:localDate.plusDays(5)
    • 减少天数:localDate.minusDays(5)
    • 增加月数:localDate.plusMonths(2)
    • 减少月数:localDate.minusMonths(2)
    • 增加年数:localDate.plusYears(1)
    • 减少年数:localDate.minusYears(1)
  5. 格式化日期:

    • 使用预定义格式化模式:localDate.format(DateTimeFormatter.ISO_DATE)
    • 自定义格式化模式:localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
  6. 解析日期字符串:

    • 使用预定义格式解析:LocalDate.parse("2022-10-01")
    • 使用自定义格式解析:LocalDate.parse("20221001", DateTimeFormatter.ofPattern("yyyyMMdd"))

java.time.LocalDateTime

Java.time.LocalDateTime是java8中的一个类,用于表示本地日期时间。它提供了一种处理日期和时间的方式,包括日期和时间的获取、操作、格式化等。

下面是LocalDateTime的一些常用方法:

  • static LocalDateTime now():返回当前的日期和时间。
  • static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute):根据年份、月份、日、小时和分钟创建一个LocalDateTime实例。
  • int get(ChronoField field):获取指定字段的值,例如YEAR表示获取年份,MONTH_OF_YEAR表示获取月份等。
  • int getYear()/getMonthValue()/getDayOfMonth()...:分别获取年份、月份、日等。
  • LocalDateTime plus(long amountToAdd, TemporalUnit unit):在当前的日期时间上增加指定的时间量,并返回新的LocalDateTime实例。
  • LocalDateTime minus(long amountToSubtract, TemporalUnit unit):在当前的日期时间上减去指定的时间量,并返回新的LocalDateTime实例。
  • Temporal adjustInto(Temporal temporal):将此LocalDateTime调整为与指定的Temporal接近的日期时间。
  • boolean isBefore(ChronoLocalDateTime<?> other):检查此日期时间是否在指定日期时间之前。
  • boolean isAfter(ChronoLocalDateTime<?> other):检查此日期时间是否在指定日期时间之后。
  • Period until(ChronoLocalDateTime<?> endExclusive):计算从此日期时间到指定日期时间之间的时间差。
  • Duration until(Temporal endExclusive):计算从此日期时间到指定日期时间之间的持续时间。
  • LocalDateTime with(TemporalAdjuster adjuster):返回一个根据指定调整器调整了的副本。
  • LocalDateTime with(TemporalField field, long newValue):返回一个由指定字段修改的副本。

 示例代码如下

// 获取当前日期和时间
LocalDateTime now = LocalDateTime.now();
System.out.println("当前日期和时间:" + now);

// 获取年份、月份、日
int year = now.getYear();
int month = now.getMonthValue();
int day = now.getDayOfMonth();
System.out.println("年:" + year + " 月:" + month + " 日:" + day);

// 增加或减少天数
LocalDateTime dateTime1 = now.plusDays(1);
LocalDateTime dateTime2 = now.minusDays(1);
System.out.println("增加一天后的日期和时间:" + dateTime1);
System.out.println("减少一天后的日期和时间:" + dateTime2);

// 修改日期和时间
LocalDateTime newDateTime1 = now.withYear(2023);
LocalDateTime newDateTime2 = now.withMonth(12);
LocalDateTime newDateTime3 = now.withDayOfMonth(25);
System.out.println("修改年份后的日期和时间:" + newDateTime1);
System.out.println("修改月份后的日期和时间:" + newDateTime2);
System.out.println("修改日后的日期和时间:" + newDateTime3);

// 自定义日期和时间
LocalDateTime customDateTime = LocalDateTime.of(2023, 5, 13, 8, 30, 0);
System.out.println("自定义日期和时间:" + customDateTime);

// 格式化日期和时间
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formattedDateTime = now.format(formatter);
System.out.println("格式化后的日期和时间:" + formattedDateTime);

  

输出:

当前日期和时间:2023-10-25T22:09:44.943074800
年:2023 月:10 日:25
增加一天后的日期和时间:2023-10-26T22:09:44.943074800
减少一天后的日期和时间:2023-10-24T22:09:44.943074800
修改年份后的日期和时间:2023-10-25T22:09:44.943074800
修改月份后的日期和时间:2023-12-25T22:09:44.943074800
修改日后的日期和时间:2023-10-25T22:09:44.943074800
自定义日期和时间:2023-05-13T08:30
格式化后的日期和时间:2023-10-25 22:09:44

  

Instant类

Instant是一个瞬时(时间点),代表了从1970-01-01T00:00:00Z开始的指定秒数。它是java.time包中唯一一个没有对应的本地日期时间的类。

public class TestInstant {
    public static void main(String[] args) {
        Instant instant = Instant.now();
        System.out.println("当前时间戳:" + instant.toEpochMilli());

        long epochSecond = System.currentTimeMillis() / 1000;
        Instant fromEpochSecond = Instant.ofEpochSecond(epochSecond);
        System.out.println("自1970年1月1日以来的秒数:" + fromEpochSecond.getEpochSecond());
    }
}

  

输出:

当前时间戳:1698243214842
自1970年1月1日以来的秒数:1698243214

  

 Duration类

Duration表示一段时间,可以通过以下方式创建实例:

  • Duration.between(start, end):计算两个时间之间的时间差。
  • Duration.ofDays(n):创建n天的时间差。
  • Duration.ofHours(n):创建n小时的时间差。
  • Duration.ofMinutes(n):创建n分钟的时间差。
  • Duration.ofSeconds(n):创建n秒钟的时间差。

常用方法主要有:

  • toDays():获取以天为单位的时间差。
  • toHours():获取以小时为单位的时间差。
  • toMinutes():获取以分钟为单位的时间差。
  • toMillis():获取以毫秒为单位的时间差。

示例:

import java.time.Duration;
import java.time.LocalDateTime;

public class TestDuration {
    public static void main(String[] args) {
        LocalDateTime dateTime1 = LocalDateTime.of(2019, 5, 1, 12, 0, 0);
        LocalDateTime dateTime2 = LocalDateTime.of(2020, 5, 1, 12, 0, 0);

        Duration duration = Duration.between(dateTime1, dateTime2);
        System.out.println("时间差为:" + duration.toDays() + "天");
        System.out.println("时间差为:" + duration.toHours() + "小时");
        System.out.println("时间差为:" + duration.toMinutes() + "分钟");
        System.out.println("时间差为:" + duration.toMillis() + "毫秒");

        Duration twoHours = Duration.ofHours(2);
        System.out.println("两个小时后的日期和时间:" + dateTime1.plus(twoHours));
    }

}

  

输出:

时间差为:366天
时间差为:8784小时
时间差为:527040分钟
时间差为:31622400000毫秒
两个小时后的日期和时间:2019-05-01T14:00

  

Period类

Period表示一段时间,如几年几个月几天。Period是以年、月、日形式表示日期时间差。

创建Period实例的方式如下:

  • Period.between(startDate, endDate):计算两个日期之间的时间差。

常用方法主要有:

  • getDays():获取天数。
  • getMonths():获取月数。
  • getYears():获取年数。

示例代码如下:

import java.time.LocalDate;
import java.time.Period;

public class TestPeriod {
    public static void main(String[] args) {
        LocalDate date1 = LocalDate.of(2020, 11, 26);
        LocalDate date2 = LocalDate.of(2021, 10, 21);

        Period period = Period.between(date1, date2);
        System.out.println("时间差为:" + period.getYears() + " 年");
        System.out.println("时间差为:" + period.getMonths() + " 个月");
        System.out.println("时间差为:" + period.getDays() + " 天");
    }

}

  

输出:

时间差为:0 年
时间差为:10 个月
时间差为:25 天

  

TemporalAdjuster接口

TemporalAdjuster是一个函数式接口,定义了一种指定日期时间调整规则的方式。

该接口包含了一个抽象方法adjustInto(Temporal temporal),接受一个Temporal参数并返回一个调整后的Temporal实例。

TemporalAdjusters类提供了一些常见的日期时间调整器实现。例如,可以使用TemporalAdjusters.firstDayOfMonth()方法获取当前月份的第一天,或者使用TemporalAdjusters.lastDayOfMonth()方法获取当前月份的最后一天。

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;

public class TestTemporalAdjuster {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        System.out.println("当前日期和时间:" + now);
        // 含时间
        LocalDateTime firstDayOfMonth = now.with(TemporalAdjusters.firstDayOfMonth());
        System.out.println("本月第一天:" + firstDayOfMonth);

        // 只有日期
        LocalDate lastDayOfMonth = now.toLocalDate().with(TemporalAdjusters.lastDayOfMonth());
        System.out.println("本月最后一天:" + lastDayOfMonth);

    }

}

  

输出:

当前日期和时间:2023-10-25T22:22:27.885662800
本月第一天:2023-10-01T22:22:27.885662800
本月最后一天:2023-10-31

  

 DateTimeFormatter类

DateTimeFormatter提供了格式化和解析日期时间的功能。通过DateTimeFormatterofPattern(String pattern)方法可以创建一个自定义的格式化器。

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class TestDateTimeFormatter {
    public static void main(String[] args) {
        LocalDateTime dateTime = LocalDateTime.now();

        // 使用内置格式化器进行格式化
        String formattedDateTime1 = dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
        System.out.println("默认格式化结果:" + formattedDateTime1);

        // 使用自定义格式化器进行格式化
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
        String formattedDateTime2 = dateTime.format(formatter);
        System.out.println("自定义格式化结果:" + formattedDateTime2);
    }

}

  

输出:

默认格式化结果:2023-10-25T22:24:12.6833186
自定义格式化结果:2023/10/25 22:24:12

 

 

ZoneIdZonedDateTime用于处理不同时区的问题

 

 

posted @ 2023-10-25 00:37  Allen_Hao  阅读(970)  评论(0)    收藏  举报