时区设置
说明
一般研发中可能涉及的时区:数据库、代码中。
咱们所在时区为东八区,而默认时区为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是两种用于存储日期和时间的数据类型。
-
datetime数据类型:datetime存储了一个特定的日期和时间,范围从'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。它使用8个字节来存储,并且不受时区影响。当您插入或查询datetime值时,它将以原样存储和检索。
-
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。
在选择使用datetime和timestamp类型时,可以根据以下几个方面进行考虑:
-
存储范围:
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类型。 -
存储精度:
datetime类型具有毫秒级别的精度,而timestamp类型只能精确到秒。如果需要更高的精度,应选择datetime类型。 -
时区处理:
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新增的日期类,用于表示年月日的日期。
特点:
- LocalDate是不可变的类,可以确保线程安全;
- LocalDate的实例不能修改,只能通过with方法创建一个新的对象;
- LocalDate是final类型且有多个静态工厂方法创建;
- LocalDate是值类型,可以通过isEqual比较两个LocalDate是否相等;
- LocalDate的格式是yyyy-MM-dd,可以通过toString、format方法进行格式化输出。
Java.time.LocalDate是Java 8中的日期类,用于表示日期。它提供了丰富的方法来操纵和获取日期信息。
以下是一些常见的用法和示例:
-
创建 LocalDate 对象:
- 使用 now() 方法获取当前日期:
LocalDate.now() - 使用 of() 方法创建指定日期:
LocalDate.of(2022, 10, 1)
- 使用 now() 方法获取当前日期:
-
获取日期信息:
- 获取年份:
localDate.getYear() - 获取月份:
localDate.getMonthValue() - 获取日:
localDate.getDayOfMonth() - 获取星期几:
localDate.getDayOfWeek()
- 获取年份:
-
比较日期:
- 判断两个日期是否相等:
localDate1.equals(localDate2) - 判断日期1是否在日期2之前:
localDate1.isBefore(localDate2) - 判断日期1是否在日期2之后:
localDate1.isAfter(localDate2)
- 判断两个日期是否相等:
-
操纵日期:
- 增加天数:
localDate.plusDays(5) - 减少天数:
localDate.minusDays(5) - 增加月数:
localDate.plusMonths(2) - 减少月数:
localDate.minusMonths(2) - 增加年数:
localDate.plusYears(1) - 减少年数:
localDate.minusYears(1)
- 增加天数:
-
格式化日期:
- 使用预定义格式化模式:
localDate.format(DateTimeFormatter.ISO_DATE) - 自定义格式化模式:
localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
- 使用预定义格式化模式:
-
解析日期字符串:
- 使用预定义格式解析:
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提供了格式化和解析日期时间的功能。通过DateTimeFormatter的ofPattern(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
ZoneId和ZonedDateTime用于处理不同时区的问题

浙公网安备 33010602011771号