为日历对象禁用 DST
Posted
技术标签:
【中文标题】为日历对象禁用 DST【英文标题】:Disable DST for Calendar object 【发布时间】:2021-01-24 15:36:27 【问题描述】:我正在解析一个逗号分隔的文件,该文件有两个需要转换为时间戳的字段。我得到了一个日期,一个单独的字段给了我午夜过去的分钟数......例如:
2020 年 10 月 15 日,360 度
现在 360,在大多数日子里,是早上 6 点(360/60 = 6),但在 DST 上说它可能是 5 点或 7 点。问题是我总是希望输出早上 6 点,即使它是 DST 日。
Calendar cal = Calendar.getInstance();
cal.setTime(schedDate);
cal.add(Calendar.MINUTE, Integer.parseInt(minutes));
return new Timestamp(cal.getTimeInMillis());
我尝试添加以下内容:
cal.set(cal.DST_OFFSET, 0);
但这似乎并不能解决问题。我不确定日历是否有任何内置功能来禁用 DST 偏移,但任何建议都将不胜感激
【问题讨论】:
这取决于哪个时区或偏移量?系统之一还是一些固定的? 我猜有没有?我采用系统默认设置,但无论它在哪个时区运行,我都希望 360 等于一年中的每一天早上 6 点。 然后使用@ArvindKumarAvinash 或我的答案给出的答案...两者都将分钟添加到解析的日期,以获得所需的一天中的时间。 我建议您既不要使用Calendar
,也不要使用java.sql.Timestamp
。这些类设计不佳且早已过时,尤其是前者,尤其是出了名的麻烦。而是使用来自java.time, the modern Java date and time API 的类。
【参考方案1】:
使用LocalDateTime
,它不需要处理时区(因此也需要处理 DST)。请注意,LocalDateTime
是 the modern date-time API 的一部分。
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Main
public static void main(String[] args)
LocalDateTime ldt = LocalDate.parse("10/15/2020", DateTimeFormatter.ofPattern("M/d/u")).atStartOfDay()
.plusHours(6);
System.out.println(ldt);
输出:
2020-10-15T06:00
我还建议您停止使用容易出错且已过时的java.util
date-time API。
如果您正在为您的 android 项目执行此操作,并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring 和 How to use ThreeTenABP in Android Project。
通过 Trail: Date Time 了解有关现代日期时间 API 的更多信息。
【讨论】:
【参考方案2】:使用java.time
,可以涉及系统的时区,也可以给它一个固定的时区。
下面的代码展示了如何做到这一点:
public static void main(String[] args)
// example input
String date = "10/15/2020";
long minutes = 360;
// create a LocalDate from the String considering its format
LocalDate localDate = LocalDate.parse(date, DateTimeFormatter.ofPattern("MM/dd/uuuu"));
// create a minimum LocalTime (the beginning of a day) and add the minutes you got
LocalTime timeOfDay = LocalTime.MIN.plusMinutes(minutes);
// create a zone-aware object by using the date, the time of day and the system's zone
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDate,
timeOfDay,
ZoneId.systemDefault());
// print the toString() method (implicitly)
System.out.println(zonedDateTime);
// or use a custom format
System.out.println(zonedDateTime.format(DateTimeFormatter
.ofPattern("MM/dd/uuuu HH:mm:ss")));
它输出以下内容(在 UTC+2 的系统上运行):
2020-10-15T06:00+02:00[Europe/Berlin]
10/15/2020 06:00:00
【讨论】:
【参考方案3】:现在,我们可以让 java.time 解析 CSV 文件(逗号分隔值文件)中的两个字段并将它们组合起来:
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("M/d/u");
DateTimeFormatter minuteOfDayFormatter = new DateTimeFormatterBuilder()
.appendValue(ChronoField.MINUTE_OF_DAY)
.toFormatter();
String dateString = "10/15/2020";
String timeString = "360";
LocalDate date = LocalDate.parse(dateString, dateFormatter);
LocalTime time = LocalTime.parse(timeString, minuteOfDayFormatter);
LocalDateTime dateTime = date.atTime(time);
System.out.println(dateTime);
输出是:
2020-10-15T06:00
如果您认为您的 SQL 数据库需要 java.sql.Timestamp
,那么您很可能不需要。您可以使用例如PreparedStatement.setObject()
将LocalDateTime
对象传递到您的数据库。如果您需要控制时区(通常是个好主意),请先将其转换为OffsetDateTime
或Instant
。搜索方法。
【讨论】:
这正是我在阅读了 Arvind 和 deHaar 的回复后所做的!谢谢你让我觉得我在正确的道路上哈哈。以上是关于为日历对象禁用 DST的主要内容,如果未能解决你的问题,请参考以下文章
Java 日历:凌晨 1 点切换到标准时间(从 DST 开始)