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年12月日历年的屏幕截图,显示标准的基于周的年份周

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访问TemporalFieldIsoFields类定义了您需要的常量。

 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 。 调用equalsisBeforeisAfter方法。

 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.DateCalendarSimpleDateFormat

现在处于维护模式的Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。

您可以直接与数据库交换java.time对象。 使用符合JDBC 4.2或更高版本的JDBC驱动程序 。 不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

  • Java SE 8Java SE 9及更高版本
    • 内置。
    • 带有捆绑实现的标准Java API的一部分。
    • Java 9增加了一些小function和修复。
  • Java SE 6Java SE 7
    • 许多java.timefunction都被反向移植到ThreeTen-Backport中的 Java 6和7。
  • Android的
    • 更高版本的Android捆绑java.time类的实现。
    • 对于早期的Android(<26), ThreeTenABP项目采用ThreeTen-Backport (如上所述)。 请参见如何使用ThreeTenABP ….