我有一个具有年和周字段的SQL数据库,我需要获取月份数据。当我试图检索它时,它给了我一个月后的一个月。例如,从2019.01.28-2019.02.01周开始,我得到月份编号2.
有什么问题?
(加上信息:我也试过了其他day_of_week)
以下是代码:
rs = stmt.executeQuery("SELECT * FROM " + sqlDatabase.beosztas() + " WHERE id = \'" + id + "\'");`
ResultSetMetaData md = rs.getMetaData();
while (rs.next()) {
year = rs.getInt(2);
week = rs.getInt(3);
cal.set(Calendar.YEAR, year);
cal.set(Calendar.WEEK_OF_YEAR, week);
cal.set(Calendar.DAY_OF_WEEK, 1);
if (count == 0) {
month = cal.get(Calendar.MONTH) + 1;
}
count++;
}
答案 0 :(得分:1)
Calendar.DAY_OF_WEEK从星期日开始,而不是星期一。所以在你的情况下,它正常返回周日的月份。如果您想将日期设置为星期一,只需使用:
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
使用日历时应该小心。 Calendar.MONTH是从0开始的索引,Calendar.DAY_OF_WEEK是从1开始的索引。
因此,您应该使用日历中定义的常量,如Calendar.MONDAY或Calendar.JUNE,以确保您使用正确的月份或日期而不会出错。
为了友好地使用Calendar,常量更好。 想要定义2018-02-18的日期:
Calendar cal = Calendar.getInstance();
cal.set(2018, 2, 18); // wrong. here the date will be 2018-03-18
cal.set(2018, Calendar.FEBRUARY, 18); // correct
答案 1 :(得分:1)
DAY_OF_WEEK
1并不代表一周的第一天。
正如DAY_OF_WEEK
的javadoc所说:
获取和设置的字段编号,表示星期几。此字段包含值
SUNDAY
,MONDAY
,TUESDAY
,WEDNESDAY
,THURSDAY
,FRIDAY
和SATURDAY
。
SUNDAY
常量的值为1,因此DAY_OF_WEEK
1表示星期日。
要指定一周的第一天,您需要致电getFirstDayOfWeek()
:
获取一周的第一天;例如,美国
SUNDAY
,法国MONDAY
。
所以:
int year = 2019;
int week = 5;
Calendar cal = Calendar.getInstance(Locale.US);
cal.clear();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.WEEK_OF_YEAR, week);
cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
System.out.println(cal.getTime());
cal = Calendar.getInstance(Locale.FRANCE);
cal.clear();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.WEEK_OF_YEAR, week);
cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
System.out.println(cal.getTime());
输出
Sun Jan 27 00:00:00 EST 2019
Mon Jan 28 00:00:00 EST 2019
在这两种情况下,你都会获得一月份。
第14周的输出
Sun Mar 31 00:00:00 EDT 2019
Mon Apr 01 00:00:00 EDT 2019
这里的地方很重要,你会得到哪个月。
答案 2 :(得分:1)
2019年第5周确实包括从一月到二月的几天,具体取决于您对周的定义。
YearWeek.parse( "2019-W05" ).atDay( DayOfWeek.MONDAY ).toString()
2019-01-28
…和…
YearWeek.parse( "2019-W05" ).atDay( DayOfWeek.SUNDAY ).toString()
2019-02-03
您忽略了解释周的定义。上面使用标准ISO 8601 week。几周甚至几个月都是日历周。
您对一周的定义是什么? #1周从1月1日开始吗?还是一周从1月1日之前的某个星期几开始?还是第一周是新年的第一周?或者,根据ISO 8601 standard's week,每周是否从星期一开始,第1周包含新日历年的第一个星期四,而一年则由52或53个完整的星期组成,可能最后一个星期或日历年的前几天结束于下一个/上一个基于周的年份?
我将接受ISO 8601培训。参见此list for 2019。
2018-W52 December 24, 2018 December 30, 2018
2019-W01 December 31, 2018 January 6, 2019
2019-W02 January 7, 2019 January 13, 2019
2019-W03 January 14, 2019 January 20, 2019
2019-W04 January 21, 2019 January 27, 2019
2019-W05 January 28, 2019 February 3, 2019
2019-W06 February 4, 2019 February 10, 2019
您正在使用的Calendar
类很糟糕,由不了解日期时间处理的复杂性和微妙性的人员设计。与Java捆绑在一起的旧的日期时间类是新的遗产,由JSR 310中定义的 java.time 取代。
在Calendar
的许多问题中,一周的定义因地区而异。您的代码忽略了语言环境的关键问题。因此,JVM的当前默认语言环境是隐式应用的。这意味着您的结果在运行时可能会有所不同。永远不要使用此类的许多原因之一。
现代解决方案涉及:
YearWeek
类具有年和周字段的SQL数据库
我建议您改用一个文本字段。年份和星期均使用标准ISO 8601格式:yyyy-Www,例如2010-W01。请注意,这种格式如何导致字母排序也按时间顺序排列。
使用YearWeek
类解析此类值。
YearWeek yearWeek = YearWeek.parse( "2019-W05" ) ;
如果您坚持将以周为单位的年数与周数分开,请使用此工厂方法来获取YearWeek
对象。
YearWeek yearWeek = YearWeek.of( 2019 , 5 ) ; // Pass number of the week-based-year and of the week.
生成ISO 8601字符串。
String output = yearWeek.toString() ;
获取该周的第一天,总是一个星期一。
LocalDate start = yearWeek.atDay( DayOfWeek.MONDAY ) ;
最后一天,通常是星期日。
LocalDate stop = yearWeek.atDay( DayOfWeek.SUNDAY ) ;
生成标准ISO 8601格式的文本。
String report = "Week " + yearWeek + " = " + start + "/" + stop ;
2019-W05周= 2019-01-28 / 2019-02-03
因此您可以看到2019年的第5周确实从1月28日(第1个月)到2月3日(第2个月)运行。
java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和SimpleDateFormat
。
要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
目前位于Joda-Time的maintenance mode项目建议迁移到java.time类。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
在哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval
,YearWeek
,YearQuarter
和more。