【问题标题】:Calculate specific date given a day of week and instance of week in the month计算给定一周中的某一天和该月的一周实例的特定日期
【发布时间】:2015-04-16 02:38:11
【问题描述】:

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

-星期几(M、T、W 等) -实例周(每月的第 2 或第 3 周)

我建议了一个 Apex 解决方案,我们将提前一个月设置一个日期变量,计算该月的第一天是星期几,然后循环遍历它,直到我们到达我们选择的“星期几”。那时,我们可以将 7 天或 14 天添加到该值上,这将为我们提供每月第二周或第三周特定日期所需的信息。

唯一的问题是每晚需要检查和更新大约 2000 条记录,而我的公司不愿意让这件事留给每晚的工作来检查和更新该字段。

我一直在查找可以在公式字段中设置的方程式,该公式字段将能够向我显示我们将调用它的“下一个服务日期”,并且公式字段将能够在页面的任何时候计算此日期被查看。 (或为此导出的报告)。

我完全陷入了一个数学方程式,该方程式将使用今天的日期来查找下个月一周中特定日期的第二个或第三个实例。我觉得从研究中可以只用一个方程来做到这一点,但我很清楚。

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

【问题讨论】:

  • 我相信您的要求是可能的,但如果某些信息可用,它会更容易。星期几、月份中的某一天、月份和年份是否可作为单独的变量使用?什么编程语言?
  • Edward- 我希望通过他们的公式字段在 Force.com 平台上实现这一点。它们具有返回月份和日期数值的函数,我认为计算出这一点的等式将涉及获取这些日期值的 if 语句。通过存在的字段和当前日期,我会说所有将进入计算的月份和日期选项都可以使用。
  • 不幸的是,您还需要知道年份,以便确定 2 月是 28 天还是 29 天。如果您知道当天的星期几,它也会非常有用。 (这可以通过另一个残酷的公式来计算,但如果系统提供它会容易得多。)
  • 我对 Force.com 平台一无所知,但我可以在任何具有模数/余数(我知道的大多数语言中的百分比)和无余数整数除法的任何平台上进行纯数学计算(/ 其中两个操作数都是整数)。在整数除法中,3/2 = 1 而不是 1.5。平台有这些功能吗?
  • 爱德华——感谢您的回复。我确实有能力向上或向下舍入,或者到我指定的任何最接近的数字。它还有一个 MOD 函数,可以返回余数。我也有能力抢年。这是我用来获得您答案的参考资料:help.salesforce.com/apex/…

标签: date math salesforce formula apex


【解决方案1】:

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

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

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

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

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

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

【讨论】:

  • 这似乎对我有用。非常感谢!数学有时让我吃惊……
【解决方案2】:

令人惊讶的是,仅使用数学公式就可以找到给定工作日的第 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
  }

}

【讨论】:

    猜你喜欢
    • 2010-09-22
    • 1970-01-01
    • 2015-10-07
    • 1970-01-01
    • 1970-01-01
    • 2019-05-14
    • 2021-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多