管理日期我正在使用班级日历。我正在使用
在数据库中保存时间戳日历时间戳= Calendar.getInstance();
我可以使用长值来保存和检索数据库中的日期来存储日期。
这是我的问题:当我有一个时间戳存储时,我需要知道在数据库中是否已经存在属于同一周的时间戳。要做到这一点,我想我可以使用几种方法:
timestamp.get(Calendar.YEAR)和 timestamp.get(Calendar.WEEK_OF_YEAR)
唯一地标识一周,但是对于连续两年都有几天的情况,情况并非如此。
这是我在2014年最后一周得到的一个例子。
2014年12月27日星期六 年:2014年 周:52
2014年12月28日星期日 年:2014年 周:1
2014年12月29日,星期一 年:2014年 周:1
2014年12月30日,星期二 年:2014年 周:1
2014年12月31日,星期三 年:2014年 周:1
2015年1月1日星期四 年:2015年 周:1
2015年1月2日星期五 年:2015年 周:1
2015年1月3日星期六 年:2015年 周:1
2015年1月4日星期日 年:2015年 周:2
从2014年12月28日到2015年3月1日的日期属于同一周(在星期日从星期日开始的java),但他们有不同的一年,所以这对夫妇(年,WEEK_OF_YEAR)没有告诉我他们属于同一周的信息。
我该如何解决?
答案 0 :(得分:1)
正如@basil建议的那样,我尝试了Joda-Time库,我找到了解决问题的方法。 要获得一年中的一周,我可以使用方法 getWeekOfWeekyear()并获得年份我可以使用方法 getWeekyear()
通过这种方式,这两个值唯一地标识属于同一周的那一天,周从星期一开始到星期日结束(与Java日历类相比的另一个附加值)。
遵循相同的问题示例。
DateTime[] timestamp = new DateTime[10];
for(int i=0; i<10; i++){
//set the start of the period
DateTime time = new DateTime(2014, 12, 27, 18, 30, 50);
//add i days to the start date
timestamp[i] = time.plus(Period.days(i));
int weekYear = timestamp[i].getWeekyear();
int weekOfWeekyear = timestamp[i].getWeekOfWeekyear();
Log.d(Constants.LOG_TAG, timestamp[i].toString("EEEE, MMMM d, yyyy") + " | year.week = " + weekYear + "." + weekOfWeekyear);
}
结果是:
2014年12月27日星期六| year.week = 2014.52
2014年12月28日星期日| year.week = 2014.52
2014年12月29日,星期一| year.week = 2015.1
2014年12月30日星期二| year.week = 2015.1
2014年12月31日星期三| year.week = 2015.1
2015年1月1日星期四| year.week = 2015.1
2015年1月3日星期六| year.week = 2015.1
2015年1月4日星期日| year.week = 2015.1
2015年1月5日星期一| year.week = 2015.2
看起来使用这个库有很多其他优点,它对我必须执行的其他计算很有用。
谢谢@basil。
答案 1 :(得分:0)
要获取相对于日期的一周的第一天和最后一天,请执行以下操作:
Calendar cal = Calendar.getInstance();
cal.setTime(date); // date to check
cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
Date startOfWeek = cal.getTime();
cal.add(Calendar.DAY_OF_MONTH, 6);
Date endOfWeek = cal.getTime();
免责声明:我从How to get the first day of the current week and month?
中偷走了部分内容然后使用检查日期范围的where
子句。
SELECT * FROM mytable WHERE mydate >= ? AND mydate <= ?
如果您的存储日期包含时间,则您希望下周开始时为上限边界,方法是添加7
而不是6
天。
SELECT * FROM mytable WHERE mydate >= ? AND mydate < ?
要显示日期逻辑,这里有一些测试代码:
// Start on 12/27/2014
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(2014, Calendar.DECEMBER, 27);
// Collect 10 dates to test (start date + next 9 days)
Date[] dates = new Date[10];
dates[0] = cal.getTime();
for (int i = 1; i < dates.length; i++) {
cal.add(Calendar.DAY_OF_MONTH, 1);
dates[i] = cal.getTime();
}
// Test loop
SimpleDateFormat fmt = new SimpleDateFormat("EEE d/M/yyyy");
for (Date date : dates) {
// Code to test
cal.setTime(date);
cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
Date startOfWeek = cal.getTime();
cal.add(Calendar.DAY_OF_MONTH, 6);
Date endOfWeek = cal.getTime();
// Show result
System.out.println(fmt.format(date) + " -> " + fmt.format(startOfWeek) +
" - " + fmt.format(endOfWeek));
}
输出
Sat 27/12/2014 -> Sun 21/12/2014 - Sat 27/12/2014
Sun 28/12/2014 -> Sun 28/12/2014 - Sat 3/1/2015
Mon 29/12/2014 -> Sun 28/12/2014 - Sat 3/1/2015
Tue 30/12/2014 -> Sun 28/12/2014 - Sat 3/1/2015
Wed 31/12/2014 -> Sun 28/12/2014 - Sat 3/1/2015
Thu 1/1/2015 -> Sun 28/12/2014 - Sat 3/1/2015
Fri 2/1/2015 -> Sun 28/12/2014 - Sat 3/1/2015
Sat 3/1/2015 -> Sun 28/12/2014 - Sat 3/1/2015
Sun 4/1/2015 -> Sun 4/1/2015 - Sat 10/1/2015
Mon 5/1/2015 -> Sun 4/1/2015 - Sat 10/1/2015
答案 2 :(得分:0)
您必须了解“正常”calendar year和standard week-based year之间的区别。一个日历年的第一天/最后几天可能出现在上一周/下周的年份。
2014年的日历年当然是2014年12月31日结束。但是,2014年的最后一天将在2015年下一个周基准年中落实。
2014年的最后一天2014年12月28日(日历年)结束。 2015年的第一天是基于2014年12月29日(日历年)。上面的日历图形应该清楚这些事实。
2014-12-28 = 2014-W52-7
2014-12-29 = 2015-W01-1
2015-01-01 = 2015-W01-4
询问基于周的周和年号:
myZonedDateTime.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR )
...和...
myZonedDateTime.get( IsoFields.WEEK_BASED_YEAR )
简单地说:对于一年中的最后/前几天,致电myZonedDateTime.getYear()
和myZonedDateTime.get( IsoFields.WEEK_BASED_YEAR )
的结果可能会有所不同。
现代方法使用 java.time 类来取代麻烦的旧遗留日期时间类。
使用班级日历管理日期。我使用
在数据库中保存时间戳Calendar timestamp = Calendar.getInstance();
相反,请使用ZoneDateTime
以特定区域(时区)的人使用的挂钟时间捕捉当前时刻。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
我可以使用长值来保存和检索数据库中的日期来存储日期。
不,在定义数据库列和Java代码时都使用适当的数据类型。
要在符合SQL标准的数据库中存储片刻,时间轴上的特定时刻,请将列定义为TIMESTAMP WITH TIME ZONE
。
使用JDBC 4.2及更高版本,您可以直接与数据库交换java.time对象。
myPreparedStatement.setObject( … , zdt ) ;
以UTC为单位检索Instant
,可能是另一个方向的最佳路线。然后调整到您想要的时区。
Instant instant = myResultSet.getObject( … , Instant.class ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
这是我的问题:当我有一个时间戳存储时,我需要知道在数据库中是否已经存在属于同一周的时间戳。为此,我想我可以使用几种方法:
timestamp.get(Calendar.YEAR)
和timestamp.get(Calendar.WEEK_OF_YEAR)
不幸的是,令人困惑的Calendar
类中一周的含义因地区而异。
也许您自己的定义与标准ISO 8601 definition of a week一致。
请注意,确定一周需要确定日期。确定日期需要一个时区。对于任何给定的时刻,日期在全球范围内因地区而异。因此,请清楚使用时区(ZoneId
),如上所示。换句话说,周数是上下文的;它取决于特定区域的日期。
访问TemporalField
中的ZonedDateTime::get
。 IsoFields
类定义了您需要的常量。
int week = zdt.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR ) ;
int weekBasedYear = zdt.get( IsoFields.WEEK_BASED_YEAR ) ;
更好的是,将ThreeTen-Extra库添加到项目中以使用YearWeek
类。
org.threeten.extra.YearWeek yw = YearWeek.from( zdt ) ;
唯一地标识一个星期,但是连续两年都有几个星期的情况并非如此。
这是我在2014年最后一周得到的一个例子。
2014年12月27日(星期六)年:2014周:52
在标准的一周内,2014-12-27是在第52周。
YearWeek.from( LocalDate.parse( "2014-12-27" ) ).toString()
2014-W52
2014年底碰巧登陆以为基础的一周(2015年)。
YearWeek.from( LocalDate.parse( "2014-12-31" ) ).toString()
2015-W01
您可以比较YearWeek
。致电equals
,isBefore
或isAfter
方法。
boolean sameYearWeek = YearWeek.from( someZdt ).equals( YearWeek.from( otherZdt ) )
因此,请确保在您的文档,代码注释和讨论中,您始终可以区分日历年和基于周的年份。永远不要说&#34;年份&#34;因为那非常模棱两可。
在财政年度增加更多的困惑。有些行业有自己的年份和季节定义等等。所以要小心你的条款。
永远不要假设周数的定义。确保此类数字的来源与您的周定义相同,例如ISO 8601定义。
例如,带有macOS的Calendar app supplied by Apple默认为&#34; Gregorian&#34;星期的日历定义。至于那意味着什么,我不知道,因为我找不到任何关于他们的意图/定义的文件。对于ISO 8601周,您必须change a setting away from default。
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和&amp; SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?