本文介绍了如何将从MongoDB查询获取的年和周年转换为Joda datetime?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在MongoDB聚合查询中使用$ year和$ week来分组年份和周的结果。在Java代码中,我想将返回的年份(一周)转换为DateTime对象,以便更容易地显示数据。

I'm using $year and $week in MongoDB aggregation query to group results by year and week of year. In the Java code I want to convert the returned year, week of year to a DateTime object, to allow easier presentation of the data.

似乎Joda DateTime的getWeekOfWeekyear )在MongoDB中的表现方式与$ week不同,这导致不同的日期结果。

It seems that Joda DateTime's getWeekOfWeekyear() doesn't behave the same way as $week in MongoDB, and this causes different date results.


  1. 情景1

  1. Scenario 1

MongoDB查询:

MongoDB query:

db.test.aggregate(
  {$project:
   {week: {$week: ISODate("2016-01-01T00:00:00.000Z") },
    year: {$year: ISODate("2016-01-01T00:00:00.000Z") } }
  }
)

返回:

{ "_id" : "", "week" : 0, "year" : 2016 }

当尝试将这些值转换为Joda DateTime对象时,它会抛出异常:IllegalFieldValueException。

When trying to convert those values to Joda DateTime object, it throws an exception: IllegalFieldValueException.

(new DateTime(0, DateTimeZone.UTC)).withWeekyear(2016).withWeekOfWeekyear(0).withDayOfWeek(1).toString()




  1. 场景2

  1. Scenario 2

另外,当查询2015-05-10,这是星期天。

In addition, when querying for 2015-05-10, which is Sunday.

MongoDB查询: (
{$ project:
{week:{$ week:ISODate(


MongoDB query:

db.test.aggregate(
  {$project:
   {week: {$week: ISODate("2016-01-01T00:00:00.000Z") },
    year: {$year: ISODate("2016-01-01T00:00:00.000Z") } }
  }
)

返回:

{ "_id" : "", "week" : 19, "year" : 2015 }

但是当尝试转换为Joda DateTime时,这将导致上周在2015-05-04开始:

But when trying to convert to Joda DateTime, this results in the previous week, starts at 2015-05-04:

(new DateTime(0, DateTimeZone.UTC)).withWeekyear(2015).withWeekOfWeekyear(19).withDayOfWeek(1).toString()

结果:

2015-05-04T00:00:00.000Z

Mongo $ week运算符将一年中的周作为0到53之间的数字。周从星期天开始,第一周从一年的第一个星期日开始。今年第一个星期日之前的天数是在第0周。在Java中,WeekOfYear返回值,一年的第一个星期是至少在今年4天。由于这一定义,第一周的第1天可能在上一年。

Mongo $week operator returns the week of the year as a number between 0 and 53. Weeks begin on Sundays, and week 1 begins with the first Sunday of the year. Days preceding the first Sunday of the year are in week 0. In Java, WeekOfYear returned value, the first week of the year is that in which at least 4 days are in the year. As a result of this definition, day 1 of the first week may be in the previous year. Also week starts on Monday.

有没有办法解决Java代码中的这种不一致?

Is there a way to solve this inconsistency in the Java code?

推荐答案

ISO 8601



Joda-Time遵循的rel =nofollow> ISO 8601 标准。

ISO 8601

Joda-Time follows the ISO 8601 standard in defining weeks.


  • 星期一是一星期的第一天。

  • 周数为1到52或53。 >
  • 周号用大写字母 W 编写,例如 W23
    年可以在前面加入 2015-W23

  • 第1周, W01 ,包含今年第一个星期四。

  • Monday is the first day of the week.
  • Weeks are numbered 1 to 52 or 53.
  • Week numbers are written with an uppercase W, such as W23.
    Year may be prepended, 2015-W23.
  • Week # 1, W01, contains the year's first Thursday.

据我所知,这个标准定义在各国的使用越来越普遍和行业。

As far as I know, this standard definition has been growing more common in usage in various countries and industries.

将周定义为:

星期几开始,第1周从一年的第一个星期日开始。今年第一个星期日之前的天数是在第0周。此行为与strftime标准库函数的%U运算符相同。

Weeks begin on Sundays, and week 1 begins with the first Sunday of the year. Days preceding the first Sunday of the year are in week 0. This behavior is the same as the "%U" operator to the strftime standard library function.

据我所知,这是一个大多数美国的定义,在美国以外没有使用。

As far as I know, this is a mostly American definition, not used much outside the US.

为什么这个定义说0到53?这意味着长达54周。我不认为这个定义在任何一年都会产生54周,但我没有想过。

Why does that definition say 0 to 53? That means "up to 54 weeks". I don't think this definition would produce 54 weeks in any year, but I've not thought it through.

你不能真正混合这两个定义。何必?如果你的目标是使用MongoDB定义的星期,并在日期的时候代表它们,然后编写你自己的转换器。

You cannot really mix the two definitions. Why bother? If your goal is to use MongoDB’s definition of weeks, and represent them by a date-time, then write your own converter.

我自己的建议是把MongoDB的定义并执行标准定义。

My own advice would be to ditch MongoDB’s definition and function, and stick with the standard definition.

如果您要查找星期天开始一个星期在MongoDB的世界,写你自己的小功能。饲料年数和周数,并返回一个DateTime。在这种情况下,您不需要Joda-Time的周年功能。

If you want to find the Sunday starting a week in MongoDB’s world, write your own little function. Feed in the year number and week number, and get back a DateTime. In this scenario, you have no need for Joda-Time’s week-of-year features.

这样的一个。

int yearNumber = 2015;
int weekNumber = 0;

LocalDate firstWeekSunday = null;
LocalDate firstOfYear = new LocalDate ( yearNumber, 1, 1 );
if ( firstOfYear.getDayOfWeek ( ) == DateTimeConstants.SUNDAY ) {
    firstWeekSunday = firstOfYear;
} else { // ELSE not Sunday.
    firstWeekSunday = firstOfYear.minusDays ( firstOfYear.getDayOfWeek ( ) );  // Joda-Time uses standard ISO 8601 weeks, where Monday = 1, Sunday = 7.
}
LocalDate sunday = firstWeekSunday.plusWeeks ( weekNumber );

DateTimeZone zone = DateTimeZone.forID ( "America/Montreal" );
DateTime dateTime = sunday.toDateTimeAtStartOfDay ( zone );

转储到控制台。

System.out.println ( "Sunday-based week of year:" + yearNumber + " week: " + weekNumber + " starts: " + sunday + "." );
System.out.println ( "Adjusted to time zone: " + zone + " is: " + dateTime + "." );

运行时

Sunday-based week of year:2015 week: 0 starts: 2014-12-28.
Adjusted to time zone: America/Montreal is: 2014-12-28T00:00:00.000-05:00.

这篇关于如何将从MongoDB查询获取的年和周年转换为Joda datetime?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-23 09:45