android如何识别一周中的同一天

时间:2015-08-30 16:53:15

标签: java android date calendar

管理日期我正在使用班级日历。我正在使用

在数据库中保存时间戳

日历时间戳= 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)没有告诉我他们属于同一周的信息。

我该如何解决?

3 个答案:

答案 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)

TL;博士

您必须了解“正常”calendar yearstandard week-based year之间的区别。一个日历年的第一天/最后几天可能出现在上一周/下周的年份。

screenshot of December 2014 month of calendar-year with indications of standard week-based year weeks

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 类来取代麻烦的旧遗留日期时间类。

  

使用班级日历管理日期。我使用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一致。

  • 第一天是星期一,一直持续到星期日。
  • 基于周的年份的第一周包含该日历年的第一个星期四。
  • 以周为基础的一年有52周或53周。
  • 一个日历年的第一个/最后几天可能会出现在上一个/下一周的年份。

请注意,确定一周需要确定日期。确定日期需要一个时区。对于任何给定的时刻,日期在全球范围内因地区而异。因此,请清楚使用时区(ZoneId),如上所示。换句话说,周数是上下文的;它取决于特定区域的日期。

访问TemporalField中的ZonedDateTime::getIsoFields类定义了您需要的常量。

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 ) ) 

术语

因此,请确保在您的文档,代码注释和讨论中,您始终可以区分日历年和基于周的年份。永远不要说&#34;年份&#34;因为那非常模棱两可。

在财政年度增加更多的困惑。有些行业有自己的年份和季节定义等等。所以要小心你的条款。

注意日历软件设置

永远不要假设周数的定义。确保此类数字的来源与您的周定义相同,例如ISO 8601定义。

例如,带有macOS的Calendar app supplied by Apple默认为&#34; Gregorian&#34;星期的日历定义。至于那意味着什么,我不知道,因为我找不到任何关于他们的意图/定义的文件。对于ISO 8601周,您必须change a setting away from default

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和&amp; SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

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

从哪里获取java.time类?