android如何识别一周的同一天
要管理日期,我正在使用class级日历。 我使用的是在DB中保存时间戳
日历时间戳= Calendar.getInstance();
我可以使用长值来保存和检索数据库中的日期来存储日期。
这是我的问题:当我有一个时间戳存储时,我需要知道在DB中是否已经存在属于同一周的时间戳。 要做到这一点,我想我可以使用几种方法:
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)不给我他们属于同一周的信息。
我怎么解决?
正如@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。
要获取相对于日期的一周的第一天和最后一天,请执行以下操作:
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();
免责声明:我从如何获得当前周和月的第一天中偷走了部分内容?
然后使用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
TL;博士
您必须了解“正常” 日历年和标准的基于周的年份之间的差异。 一个日历年的第一个/最后几天可能出现在上一个/下一周的年份中。
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
现代方法使用java.time类来取代麻烦的旧遗留日期时间类。
要管理日期,我正在使用class级日历。 我正在使用
Calendar timestamp = Calendar.getInstance();
在数据库中保存时间戳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 ) ;
作为Instant
检索,UTC中的一个时刻,可能是另一个方向上的最佳路线。 然后调整到您想要的时区。
Instant instant = myResultSet.getObject( … , Instant.class ) ; ZonedDateTime zdt = instant.atZone( z ) ;
这是我的问题:当我有一个时间戳存储时,我需要知道在DB中是否已经存在属于同一周的时间戳。 为此,我想我可以使用几种方法:
timestamp.get(Calendar.YEAR)
和timestamp.get(Calendar.WEEK_OF_YEAR)
不幸的是,令人困惑的Calendar
类中一周的含义因区域设置而异。
也许您自己的定义与一周的标准ISO 8601 定义一致 。
- 第一天是星期一,一直持续到星期天。
- 基于周的年份的第一周包含该日历年的第一个星期四。
- 以工作周为基础的一年有52周或53周。
- 一个日历年的第一个/最后几天可能出现在上一个/下一周的年份中。
请注意,确定一周需要确定日期。 确定日期需要一个时区。 对于任何给定的时刻,日期在全球范围内因地区而异。 因此,请清楚使用时区( ZoneId
),如上所示。 换句话说,周数是上下文的; 它取决于特定区域的日期。
在ZonedDateTime::get
访问TemporalField
。 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 ) )
术语
因此,请确保在文档,代码注释和讨论中始终区分日历年和基于周的年份。 永远不要说“年”,因为那是非常模糊的。
在财政年度增加更多的混乱。 有些行业有自己的年份和季节定义等等。 所以要小心你的条款。
注意日历软件设置
永远不要假设周数的定义。 确保此类数字的来源与您的周定义相同,例如ISO 8601定义。
例如, Apple提供的带有macOS的Calendar应用程序默认为周的“Gregorian”日历定义。 至于那意味着什么,我不知道,因为我找不到任何关于他们的意图/定义的文件。 对于ISO 8601周,您必须更改默认设置 。
关于java.time
java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,如java.util.Date
, Calendar
和SimpleDateFormat
。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。
您可以直接与数据库交换java.time对象。 使用符合JDBC 4.2或更高版本的JDBC驱动程序 。 不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?
- Java SE 8 , Java SE 9及更高版本
- 内置。
- 带有捆绑实现的标准Java API的一部分。
- Java 9增加了一些小function和修复。
- Java SE 6和Java SE 7
- 许多java.timefunction都被反向移植到ThreeTen-Backport中的 Java 6和7。
- Android的
- 更高版本的Android捆绑java.time类的实现。
- 对于早期的Android(<26), ThreeTenABP项目采用ThreeTen-Backport (如上所述)。 请参见如何使用ThreeTenABP ….