Github user rxin commented on a diff in the pull request:
https://github.com/apache/spark/pull/7754#discussion_r35822048
--- Diff:
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DateTimeUtils.scala
---
@@ -575,6 +576,138 @@ object DateTimeUtils {
}
/**
+ * The number of days for each month (not leap year)
+ */
+ private val monthDays = Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31,
30, 31)
+
+ /**
+ * Returns the date value for the first day of the given month.
+ * The month is expressed in months since year zero (17999 BC), starting
from 0.
+ */
+ private def firstDayOfMonth(absoluteMonth: Int): Int = {
+ val absoluteYear = absoluteMonth / 12
+ var monthInYear = absoluteMonth - absoluteYear * 12
+ var days = getDaysFromYears(absoluteYear)
+ if (monthInYear >= 2 && isLeapYear(absoluteYear + YearZero)) {
+ days += 1
+ }
+ while (monthInYear > 0) {
+ days += monthDays(monthInYear - 1)
+ monthInYear -= 1
+ }
+ days
+ }
+
+ /**
+ * Returns the date value for January 1 of the given year.
+ * The year is expressed in years since year zero (17999 BC), starting
from 0.
+ */
+ private def getDaysFromYears(absoluteYear: Int): Int = {
+ val absoluteDays = (absoluteYear * 365 + absoluteYear / 400 -
absoluteYear / 100
+ + absoluteYear / 4)
+ absoluteDays - toYearZero
+ }
+
+ /**
+ * Add date and year-month interval.
+ * Returns a date value, expressed in days since 1.1.1970.
+ */
+ def dateAddMonths(days: Int, months: Int): Int = {
+ val absoluteMonth = (getYear(days) - YearZero) * 12 + getMonth(days) -
1 + months
+ val currentMonthInYear = absoluteMonth % 12
+ val currentYear = absoluteMonth / 12
+ val leapDay = if (currentMonthInYear == 1 && isLeapYear(currentYear +
YearZero)) 1 else 0
+ val lastDayOfMonth = monthDays(currentMonthInYear) + leapDay
+
+ val dayOfMonth = getDayOfMonth(days)
+ val currentDayInMonth = if (getDayOfMonth(days + 1) == 1 || dayOfMonth
>= lastDayOfMonth) {
+ // last day of the month
+ lastDayOfMonth
+ } else {
+ dayOfMonth
+ }
+ firstDayOfMonth(absoluteMonth) + currentDayInMonth - 1
+ }
+
+ /**
+ * Add timestamp and full interval.
+ * Returns a timestamp value, expressed in microseconds since 1.1.1970
00:00:00.
+ */
+ def timestampAddInterval(start: Long, months: Int, microseconds: Long):
Long = {
+ val days = millisToDays(start / 1000L)
+ val newDays = dateAddMonths(days, months)
+ daysToMillis(newDays) * 1000L + start - daysToMillis(days) * 1000L +
microseconds
+ }
+
+ /**
+ * Returns the last dayInMonth in the month it belongs to. The date is
expressed
+ * in days since 1.1.1970. the return value starts from 1.
+ */
+ private def getLastDayInMonthOfMonth(date: Int): Int = {
+ var (year, dayInYear) = getYearAndDayInYear(date)
+ if (isLeapYear(year)) {
+ if (dayInYear > 31 && dayInYear <= 60) {
+ return 29
+ } else if (dayInYear > 60) {
+ dayInYear = dayInYear - 1
+ }
+ }
+ if (dayInYear <= 31) {
+ 31
+ } else if (dayInYear <= 59) {
+ 28
+ } else if (dayInYear <= 90) {
+ 31
+ } else if (dayInYear <= 120) {
+ 30
+ } else if (dayInYear <= 151) {
+ 31
+ } else if (dayInYear <= 181) {
+ 30
+ } else if (dayInYear <= 212) {
+ 31
+ } else if (dayInYear <= 243) {
+ 31
+ } else if (dayInYear <= 273) {
+ 30
+ } else if (dayInYear <= 304) {
+ 31
+ } else if (dayInYear <= 334) {
+ 30
+ } else {
+ 31
+ }
+ }
+
+ /**
+ * Returns number of months between time1 and time2. time1 and time2 are
expressed in
+ * microseconds since 1.1.1970
--- End diff --
we should document that this returns an integer if it is the same day in
each month
---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at [email protected] or file a JIRA ticket
with INFRA.
---
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]