tl;博士
我正在寻找一些 Java 中的官方常量
是的,Java 使用与 Postgres 中的 isodow 函数相同的标准 ISO 8601 定义在 DayOfWeek 枚举中定义一周中的 7 天值,其中一周从星期一到星期日运行,天数为 1-7 .
DayOfWeek.WEDNESDAY.getValue() // Returns an `int` 1-7 for Monday-Sunday.
3
java.time.DayOfWeek枚举
正如Answer by Rcordoval 建议的那样,使用Postgres function isodow。
isodow 中的“iso”指的是ISO 8601 标准和its definition of week,其中周一至周日的天数为 1-7。
Java 在其DayOfWeek 枚举中支持相同的星期定义。该类为您定义了七个对象,一个用于一周中的每一天,例如DayOfWeek.MONDAY。要获取每个对象的星期几编号(周一至周日为 1-7),请致电 DayOfWeek::getValue。但在您的 Java 编码中,请专注于使用和传递 DayOfWeek 对象本身,而不仅仅是整数。
int dowNumber = DayOfWeek.WEDNESDAY.getValue() ;
3
从整数到 DayOfWeek 对象有点棘手,因为我们需要使用索引访问 Java 数组。该指数表示从零开始计数,因此请从您的星期数中减去 1。星期三是第 3 天,因此 2 的结果减去 1 即可访问DayOfWeek.WEDNESDAY。
DayOfWeek dow = DayOfWeek.values()[ 3-1 ] ; // Get object named `WEDNESDAY` using zero-based index counting, so 3 - 1 = 2.
dow.toString(): 星期三
顺便说一句,要自动本地化星期几的名称,请致电DayOfWeek::getDisplayName。
Java 而非 SQL
我目前正在编写一个查询,该查询正在查找当前在各自时区具有星期五上午 10:00 的客户,因此我需要将“星期五”的概念传递到查询中,当然我不需要想要硬编码。
使用行业领先的 java.time 类在 Java 中完成这项工作可能比在 SQL 中更好。
您必须非常小心时区。明确时区,而不是依赖隐含的默认时区。
时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因区域而异。例如,Paris France 的午夜后几分钟是新的一天,而 Montréal Québec 仍然是“昨天”。
如果没有指定时区,JVM 会隐式应用其当前的默认时区。该默认值可能随时更改,因此您的结果可能会有所不同。最好将您想要/预期的时区明确指定为参数。
以continent/region 的格式指定proper time zone name,例如America/Montreal、Africa/Casablanca 或Pacific/Auckland。切勿使用 3-4 个字母的缩写,例如 EST 或 IST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
如果你想使用 JVM 当前的默认时区,请求它并作为参数传递。如果省略,则隐式应用 JVM 的当前默认值。最好是明确的,因为默认值可能会在任何时候在运行时被 JVM 中任何应用程序的任何线程中的任何代码更改。
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
接下来,争取下一个星期五,如果已经是星期五,就坚持今天。使用TemporalAdjuster 在日期之间进行调整,特别是在TemporalAdjusters 中找到的那个。
LocalDate nextOrSameFriday = today.with( TemporalAdjusters.nextOrSame( DayOfWeek.FRIDAY ) ) ;
你说你的目标是上午 10 点。
LocalTime lt = LocalTime.of( 10 , 0 ) ; // 10 AM.
结合日期和区域以获得特定时刻。
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
通过提取Instant 对象调整为UTC。同一时刻,时间轴上的同一点,但挂钟时间不同。
Instant instant = zdt.toInstant() ;
制定您的 SQL 以查询 TIMESTAMP WITH TIME ZONE 类型的数据库列。
String sql = "SELECT * from tbl WHERE when_col = ? ; " ;
…
myPreparedStatement.setObject( … , instant ) ;
和检索。
Instant instant = myResultSet.getObject( … , Instant.class ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
在这种方法中,您需要 Postgres 中的 dow 或 isodow 函数。
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。
从哪里获得 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。