计算一周中某一天的特定日期和该月的一周中的实例

时间:2015-04-16 02:38:11

标签: date math salesforce formula apex

我有一种情况需要在公式字段中计算下个月的特定日期,我必须计算的值是:

- 一周(M,T,W等) - 实习周(本月第2或第3周)

我提出了一个Apex解决方案,我们将提前一个月设置一个日期变量,计算一个月中第一天的星期几,然后循环直到我们选择的#34; Day of Day周&#34 ;.那时我们可以为该值增加7天或14天,这将为我们提供我们在特定日期的当月第二周或第三周所需的内容。

唯一的问题是大约有2000条记录需要每晚检查和更新,我的公司很不舒服,只需要通过夜间工作来更新这个字段。

我一直在查找可能在公式字段中设置的方程式,这些方程式将能够显示"下一个服务日期"我们将调用它,并且公式字段将能够在查看页面时计算此日期。 (或报告出口的报告)。

我完全停留在一个数学等式中,该数学等式将使用今天的日期来查找下个月中某一特定日期的第二或第三个实例。我觉得从研究中可以用一个方程来做到这一点,但我很惊讶。

以前有没有人做过这样的事情?任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

令人惊讶的是,可以仅使用数学公式找到给定工作日的第n次出现。下面我已经包含了Java代码来逐步进行计算。通过将公式代入其他公式,可以将公式序列简化为一个公式。我输出了很多调试信息,所以我可以关注计算的各个阶段。注意我只是轻轻地测试了程序;它应该进行广泛的投入测试,包括1995年至2017年的日期。

import java.util.Calendar;

public class NextServiceDate {

  public static int // Jan = 1, Dec = 12, Sun = 1, Sat = 7
  nextServiceDate(int year, int month, int dayOfMonth, int dayOfWeek,
                  int targetDayOfWeek, int occurrenceOfDayOfWeek) {

    // We have to do all date calculations with mathematical formulas
    // all the formulas could be mashed together, if desired

    // Want March = 1, April = 2, May = 3, ..., January = 11, February = 12
    int monthMarchIs1 = (month+9)%12 + 1;
    System.out.println("Current month, where March is 1: " + monthMarchIs1);

    // want to know whether month is February
    int isMonthFeb = monthMarchIs1 / 12; // integer division
    System.out.println("Is month February: " + isMonthFeb);

    // want to know whether year is leap year
    // is year divisible by 4?
    int isYearDivBy4 = (1-(year%4+3)/4); // 0 = false, 1 = true
    System.out.println("Is year div by 4: " + isYearDivBy4);
    // is year divisible by 100?
    int isYearDivBy100 = (1-(year%100+99)/100);
    System.out.println("Is year div by 100: " + isYearDivBy100);
    // is year divisible by 400?
    int isYearDivBy400 = (1-(year%400+399)/400);
    System.out.println("Is year div by 400: " + isYearDivBy400);
    // Boolean logic to determine whether year is leap year
    // note year div by 400 implies year div by 100 so the result is never 2
    int isLeapYear = isYearDivBy4*(1-isYearDivBy100) + isYearDivBy400;
    System.out.println("Is year leap: " + isLeapYear);

    // calculate days in month using Curtis McEnroe's formula
    // http://cmcenroe.me/2014/12/05/days-in-month-formula.html
    // corrected for leap year using Boolean logic
    int daysInMonth = 28 + (month+month/8)%2 + 2%month + 2*(1/month)
      + isMonthFeb*isLeapYear;
    System.out.println("Days in month: " + daysInMonth);

    // number of days to the first of next month
    int daysToFirst = daysInMonth - dayOfMonth + 1;
    System.out.println("Days to the first of next month: " + daysToFirst);

    // weekday of first of next month
    int weekdayOfFirst = (dayOfWeek + daysToFirst) % 7; // Sat = 0
    System.out.println("Weekday of first of next month: " + weekdayOfFirst);

    // additional days to target day of week
    int dateOfTargetWeekday = (targetDayOfWeek-weekdayOfFirst+7)%7 + 1;
    System.out.println("Date of target day of week: " + dateOfTargetWeekday);

    // final answer: day of month of target date
    int dateOfTarget = dateOfTargetWeekday + (occurrenceOfDayOfWeek-1)*7;
    System.out.println("Day of month of target date: " + dateOfTarget);
    System.out.println();

    return dateOfTarget;
  }

  public static void main(String[] args) {
    final String[] MONTHABBR = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
                                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
    Calendar rightNow = Calendar.getInstance();
    int year = rightNow.get(Calendar.YEAR);
    int month = rightNow.get(Calendar.MONTH) + 1; // Java has Jan = 0
    int dayOfMonth = rightNow.get(Calendar.DAY_OF_MONTH);
    int dayOfWeek = rightNow.get(Calendar.DAY_OF_WEEK); // Sun = 1, Sat = 7

    System.out.println("Using as current year: " + year);
    System.out.println("Using as current month: " + month);
    System.out.println("Using as current day of month: " + dayOfMonth);
    System.out.println("Using as current day of week: " + dayOfWeek);
    System.out.println();

    System.out.println("Second Tuesday of next month is " +
                       MONTHABBR[(month+1)%12] + " " +
                       nextServiceDate(year,month,dayOfMonth,dayOfWeek,
                                       3,2)); // 2nd Tuesday(=3) of next month
  }

}

答案 1 :(得分:0)

使用此问题评论中提供的参考文献中描述的语言功能,计算似乎并不那么难。要查找下个月第一天的日期值,请使用

DATE(YEAR(TODAY()), MONTH(TODAY()) + 1, 1)

要查找下个月第一天的星期几,请使用

MOD( DATE(YEAR(TODAY()), MONTH(TODAY()) + 1, 1) - DATE(1900,1,7), 7)

其中Sun = 0,... Sat = 6.要查找下个月第一天_of_week的日期,请使用

DATE(YEAR(TODAY()), MONTH(TODAY())+1, 1)
+ day_of_week 
- MOD( DATE(YEAR(TODAY()), MONTH(TODAY())+1, 1) - DATE( 1900, 1, 7 ), 7 )
+
IF( 
  MOD(DATE(YEAR(TODAY()),MONTH(TODAY())+1,1)-DATE(1900,1,7),7) >= day_of_week,
  7,
  0
)

最后,要移至所需day_of_week的第2或第3次,请使用

DATE(YEAR(TODAY()), MONTH(TODAY())+1, 1)
+ day_of_week 
- MOD( DATE(YEAR(TODAY()), MONTH(TODAY())+1, 1) - DATE( 1900, 1, 7 ), 7 )
+
IF( 
  MOD(DATE(YEAR(TODAY()),MONTH(TODAY())+1,1)-DATE(1900,1,7),7) >= day_of_week,
  7,
  0
)
+ (occurrence - 1) * 7

这比我的纯数学答案更容易,因为该语言有一种增加月份的内置方法(MONTH(TODAY())+1)。