【问题标题】:How to extract the data basis on it is Monday or Thursday in YYYYMMDD format?如何以YYYYMMDD格式提取周一或周四的数据?
【发布时间】:2014-02-26 02:10:24
【问题描述】:

我正在尝试以YYYYMMDD这种格式获取星期一或星期四的日期

星期一应该给我这个 - 20130224(例如)

星期四它应该给我这个 - 20130227(例如)

  • 现在,如果我在Thursday 之后或Thursday 上运行我的程序,它应该以YYYYMMDD 的格式打印Thursday 的日期,可以是20130227(本周星期四到来)。
  • 如果我在 MondayMonday 之后运行我的程序,那么它应该以相同的格式 YYYYMMMDD 打印星期一的日期,可以是 20130224(以昨天的星期一日期为例)

我将如何在 Java 中做到这一点?

以下是我尝试过的 -

Calendar cal = Calendar.getInstance();
SimpleDateFormat formatter = new SimpleDateFormat("EEE");
String text = formatter.format(cal.getTime());
System.out.println(text);

// but how do I check if it is Tuesday but less than Thursday
if(text.equalsIgnoreCase("Tue")) {
    // get previous Monday date in YYYYMMDD
} 

// and how do I check if it is thursday or greater than Thursday?
else if(text.equalsIgnoreCase("Thur")) {
 // get previous Thursday date in YYYYMMDD
}

更新:-

在特定的一周中,如果我在星期四或星期四之后运行我的程序,那么它应该以 YYYYMMDD 格式返回同一周星期四的日期,但如果我在星期一或星期一之后运行我的程序,那么它应该以 YYYYMMDD 格式返回同一周星期一的日期。

例如,在本周,如果我在星期四或星期四之后运行我的程序,那么它应该返回星期四的日期。但是,如果我在同一周的星期一、星期二或星期三运行我的程序,那么它应该返回星期一的日期。

代码:-

下面是我的代码-

public static void main(String[] args) {

try {
    Calendar cal = Calendar.getInstance();
    SimpleDateFormat toDateFormat = new SimpleDateFormat("yyyyMMdd");

    int dow = cal.get(Calendar.DAY_OF_WEEK);
    switch (dow) {
    case Calendar.THURSDAY:
    case Calendar.FRIDAY:
    case Calendar.SATURDAY:
    case Calendar.SUNDAY:
    while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.THURSDAY) {
        cal.add(Calendar.DATE, -1);
    }
    break;
    case Calendar.MONDAY:
    case Calendar.TUESDAY:
    case Calendar.WEDNESDAY:
    while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
        cal.add(Calendar.DATE, -1);
    }
    break;
    }

    System.out.println(date);
    System.out.println(cal.getTime());
    System.out.println(toDateFormat.format(cal.getTime()));

} catch (ParseException exp) {
    exp.printStackTrace();
}
}

【问题讨论】:

  • 你在问什么?如何从 YYYYMMDD 中日期的字符串表示中获取星期几的名称?昨天和后天有什么关系?
  • 您是否要求打印最近的周一和周四的日期?
  • 我刚刚更新了我的问题..看看,如果有什么不清楚的地方,请告诉我..
  • 好的,所以你想要 DAY IF DAY >= TODAY ELSE MONDAY?
  • 假设 - 在这周,如果我在星期四或星期四之后运行我的程序,那么它应该以 YYYYMMDD 格式返回星期四的日期。但是,如果我在同一周的星期一、星期二或星期三运行我的程序,那么它应该以 YYYYMMDD 格式返回星期一的日期。

标签: java date calendar jodatime simpledateformat


【解决方案1】:

首先将文本值解析为Date 值...

String dateText = "20130224";
SimpleDateFormat toDateFormat = new SimpleDateFormat("yyyyMMdd");
Date date = toDateFormat.parse(dateText);

这为您提供了起点。接下来,您需要使用Calendar,它可以让您前后移动,自动为您内部滚动日期(因此,如果您滚动周、月或年边界)

例如...

try {
    String dateText = "20130227";
    SimpleDateFormat toDateFormat = new SimpleDateFormat("yyyyMMdd");
    Date date = toDateFormat.parse(dateText);

    Calendar cal = Calendar.getInstance();
    cal.setTime(date);

    int dow = cal.get(Calendar.DAY_OF_WEEK);
    switch (dow) {
        case Calendar.THURSDAY:
        case Calendar.FRIDAY:
        case Calendar.SATURDAY:
        case Calendar.SUNDAY:
            while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.THURSDAY) {
                cal.add(Calendar.DATE, -1);
            }
            break;
        case Calendar.MONDAY:
        case Calendar.TUESDAY:
        case Calendar.WEDNESDAY:
            while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
                cal.add(Calendar.DATE, -1);
            }
            break;
    }

    System.out.println(date);
    System.out.println(cal.getTime());

} catch (ParseException exp) {
    exp.printStackTrace();
}

所以,根据这个例子,它会输出...

Wed Feb 27 00:00:00 EST 2013
Mon Feb 25 00:00:00 EST 2013

对于20130224(这是星期天),它会给

Sun Feb 24 00:00:00 EST 2013
Thu Feb 21 00:00:00 EST 2013

我还应该补充一点,使用 JodaTime 可能有一种更简单的方法来做到这一点,但这是我能够快速消除的。是的,我知道case 语句有点啰嗦,但是SUNDAY 等于0,这有点烦人;)

【讨论】:

  • 感谢 MadProgrammer .. 在您的示例中,您将 dateText 硬编码为.. 当我将实际运行我的程序时,我如何得到它?而且我还需要以 YYYYMMDD 格式获取星期四和星期一的日期..
  • 用你想要的任何变量替换它(dateText)......使用将String值解析为Date的原始日期格式化程序再次格式化......dateText = toDateFormat.format(cal.getTime())
  • 现在明白了。我用代码示例更新了我的问题。你能看一下,让我知道你的意思是否正确吗?
  • Calendar.getInstance() 返回一个Calendar 的实例当前日期和时间,所以你不需要格式化和解析它,使用它就可以了...
  • 当然..现在明白了..基本上你提供了一个例子让我理解..我根本不需要那些解析和格式..
【解决方案2】:

什么?转移到具有相同内容的新问题?

  String[] weeks = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
  DateFormat df = new SimpleDateFormat("yyyyMMdd");
  Calendar c = Calendar.getInstance();
  c.setTime(new Date()); // Now use today date.
  int dayOfWeek = c.get(Calendar.DAY_OF_WEEK); // Sun=1, Mon=2, ... Sat=7
  System.out.println("Today " + df.format(c.getTime()) + " is " + weeks[dayOfWeek-1]);
  c.add(Calendar.DATE, 7); // Adding 7 days
  System.out.println("Next " + weeks[dayOfWeek-1] + " is " + df.format(c.getTime()));
  // Should display:
  // Today 20140225 is Tuesday
  // Next Tuesday is 20140304

【讨论】:

  • 所以,你有 dayOfWeek 告诉你你在星期几。使用它来检测当前日期并添加或减去下一个值。例如,今天是星期二,因此 dayOfWeek=3,而您希望星期一是 2,2-3=-1,将 -1 添加到您的日历中 c.add(Calendar.DATE, -1) 将为您提供星期一。
【解决方案3】:

我会使用日历上课日来获取星期几。 Calendar.DAY_OF_WEEK 函数为星期日 - 星期六返回 1 - 7。通过这种方式,您可以进行数字比较,而不是在工作日比较字符串时乱七八糟(如果您的应用需要支持多种语言,这将是一团糟)。

见:

http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html

【讨论】:

    【解决方案4】:

    如果我明白你在追求什么,那么这应该可以工作

    private static final java.text.SimpleDateFormat sdf = 
      new java.text.SimpleDateFormat("yyyyMMdd");
    public static String calculateCorrectDate(
        java.util.Date d) {
      java.util.Calendar cal = java.util.Calendar
          .getInstance();
      cal.setTime(d);
      int dayOfWeek = cal
          .get(java.util.Calendar.DAY_OF_WEEK);
      if (dayOfWeek >= java.util.Calendar.MONDAY
          && dayOfWeek < java.util.Calendar.THURSDAY) {
        cal.set(java.util.Calendar.DAY_OF_WEEK,
            java.util.Calendar.MONDAY);
      } else {
        cal.set(java.util.Calendar.DAY_OF_WEEK,
            java.util.Calendar.THURSDAY);
      }
      return sdf.format(cal.getTime());
    }
    public static void main(String[] args) {
      java.util.List<java.util.Date> dates = new java.util.ArrayList<java.util.Date>();
      java.util.Calendar cal = java.util.Calendar
          .getInstance();
      String today = sdf.format(cal.getTime());
    
      cal.add(java.util.Calendar.DAY_OF_WEEK, -10);
      for (int i = 0; i < 20; i++) {
        dates.add(cal.getTime());
        cal.add(java.util.Calendar.DAY_OF_WEEK, 1);
      }
      for (java.util.Date d : dates) {
        if (sdf.format(d).equals(today)) {
          System.out.println("TODAY!");
        }
        System.out.println(calculateCorrectDate(d));
      }
    }
    

    输出结果

    20140213
    20140220
    20140217
    20140217
    20140217
    20140220
    20140220
    20140220
    20140227
    20140224
    TODAY!
    20140224
    20140224
    20140227
    20140227
    20140227
    20140306
    20140303
    20140303
    20140303
    20140306
    

    或有一些导入,

    // Import Static
    // This simplifies accessing the Calendar fields. Use sparingly.
    import static java.util.Calendar.DAY_OF_WEEK;
    import static java.util.Calendar.MONDAY;
    import static java.util.Calendar.THURSDAY;
    
    // The other imports.
    import java.util.Calendar;
    import java.util.Date;
    

    然后就可以使用了,

    public static String calculateCorrectDate(Date d) {
      Calendar cal = Calendar.getInstance();
      cal.setTime(d);
      // By using import static this remains concise and correct.
      int dayOfWeek = cal.get(DAY_OF_WEEK);
      if (dayOfWeek >= MONDAY && dayOfWeek < THURSDAY) {
        cal.set(DAY_OF_WEEK, MONDAY);
      } else {
        cal.set(DAY_OF_WEEK, THURSDAY);
      }
      return sdf.format(cal.getTime());
    }
    

    【讨论】:

    • 你对进口有什么看法?
    • @Obicere 什么都没有,但在这种情况下,您还应该使用 import static。此外,OP 没有指定类名,所以 ...
    • @ElliottFrisch:感谢您的建议。在您的示例中,sdf 是什么,您如何初始化 SimpleDateFormat
    • @SSH 已编辑以包含该内容。
    • 谢谢.. 快速提问.. 我是否需要您在示例中使用的这些 for 循环?基本上,我想获得星期四或星期一的日期,具体取决于我运行程序的时间以及我在问题中提到的某些条件。
    【解决方案5】:

    乔达时间


    更新:Joda-Time 项目现在位于maintenance mode,团队建议迁移到java.time 类。这个答案作为历史原封不动地保留下来。请参阅my modern Answer


    是的,Joda-Time 是解决方案。

    或 Java 8 中的新 java.time 包。受 Joda-Time 启发,但经过重新设计。由 JSR 310 定义。

    下周一/周四

    搜索 StackOverflow 以获取一周的第一天或最后一天。这将告诉你如何获得下周一或周四。我不会在这里讨论你的那部分问题。

    每周测试日

    如果您碰巧在英语不是默认语言环境的地方运行,用英语单词测试星期几很容易出错。相反,按数字获取星期几。 Joda-Time 使用ISO 8601 作为默认值,因此星期一 = 1,星期日 = 7。提供了常量,因此您无需记住数字。

    没有时间的日期

    如果您真的不关心时间,只关心日期,那么我们可以使用LocalDate 而不是DateTime

    示例代码

    一些帮助您入门的代码,使用 Joda-Time 2.3。

    String input = "20130224";
    DateTimeFormatter formatterInput = DateTimeFormat.forPattern( "yyyyMMdd" );
    LocalDate localDate = formatterInput.parseLocalDate( input );
    int dayOfWeek = localDate.getDayOfWeek();
    boolean isMonday = ( localDate.getDayOfWeek() == DateTimeConstants.MONDAY );
    boolean isThursday = ( localDate.getDayOfWeek() == DateTimeConstants.THURSDAY );
    

    转储到控制台...

    System.out.println( "localDate: " + localDate );
    System.out.println( "dayOfWeek: " + dayOfWeek );
    System.out.println( "isMonday: " + isMonday );
    System.out.println( "isThursday: " + isThursday );
    

    运行时……

    localDate: 2013-02-24
    dayOfWeek: 7
    isMonday: false
    isThursday: false
    

    【讨论】:

      【解决方案6】:

      tl;博士

      如果:

      EnumSet.range( DayOfWeek.MONDAY , DayOfWeek.WEDNESDAY )  // Monday, Tuesday, & Wednesday.
          contains( LocalDate.now().getDayOfWeek() )           // If today’s date is a day-of-week that happens to be a member of that `Set`.
      

      ……然后,申请:

       TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY )    // Adjust into an earlier `LocalDate` that is a Monday, unless today already is Monday.
      

      …其他适用:

       TemporalAdjusters.previousOrSame( DayOfWeek.THURSDAY )  // Otherwise move to a Thursday.
      

      java.time

      现代方法使用 java.time 类。解决这个问题要容易得多。

      LocalDate

      LocalDate 类表示没有时间和时区的仅日期值。

      时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因区域而异。例如,Paris France 中午夜后几分钟是新的一天,而 Montréal Québec 中仍然是“昨天”。

      如果没有指定时区,JVM 会隐式应用其当前的默认时区。该默认值可能随时更改,因此您的结果可能会有所不同。最好将您想要/预期的时区明确指定为参数。

      continent/region 的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。

      ZoneId z = ZoneId.of( "America/Montreal" ) ;  
      LocalDate today = LocalDate.now( z ) ;
      

      如果你想使用 JVM 当前的默认时区,请求它并作为参数传递。如果省略,则隐式应用 JVM 的当前默认值。最好是明确的。

      ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.
      

      或者指定一个日期。您可以通过数字设置月份,1 月至 12 月的编号为 1-12。

      LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ;  // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
      

      或者,更好的是,使用预定义的Month 枚举对象,一年中的每个月一个。提示:在整个代码库中使用这些 Month 对象,而不是仅仅使用整数,以使您的代码更具自记录性、确保有效值并提供 type-safety

      LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
      

      DayOfWeek枚举

      DayOfWeek 枚举定义了一组七个对象,一个用于一周中的每一天。

      EnumSetSet 的高度优化实现,用于收集枚举对象。所以我们可以创建一对EnumSet 对象来保存DayOfWeek 对象的集合来定义你的两个条件:(星期一和星期二)与(星期四...星期日)。

      尽管神秘地未能实现SortedSetEnumSet 确实按照枚举的自然顺序(声明顺序)排序。对于DayOfWeek,这将是周一至周日,编号为 1-7,尽管您可能永远不需要这些数字。

      Set < DayOfWeek > mondayDays = EnumSet.range( DayOfWeek.MONDAY , DayOfWeek.WEDNESDAY );  // Monday, Tuesday, & Wednesday.
      Set < DayOfWeek > thursdayDays = EnumSet.range( DayOfWeek.THURSDAY , DayOfWeek.SUNDAY );  // Thursday, Friday, Saturday, Sunday.
      

      获取源日期的星期几。准备将其与我们的枚举集进行匹配。

      LocalDate ld = LocalDate.now( ZoneId.of( "Africa/Tunis" ) ) ;  // Get today’s current date in a particular time zone.
      DayOfWeek dow = ld.getDayOfWeek();
      LocalDate target = LocalDate.EPOCH;  // Or null. The `LocalDate.EPOCH` is first moment of 1970 in UTC, 1970-01-01T00:00:00Z.
      

      查看哪个Set 具有我们日期的星期几。从那里,调整到所需星期几(星期一或星期四)的前一个或同一日期。

      if ( mondayDays.contains( dow ) )
      {
          target = ld.with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) );
      } else if ( thursdayDays.contains( dow ) )
      {
          target = ld.with( TemporalAdjusters.previousOrSame( DayOfWeek.THURSDAY ) );
      } else
      {
          System.out.println( "ERROR - Unexpectedly reached IF-ELSE. " );
      }
      

      以您想要的格式生成字符串。您选择的格式恰好是标准 ISO 8601 格式的“基本”版本,其中分隔符的使用最少。

      String output = target.format( DateTimeFormatter.BASIC_ISO_DATE ) ;  // YYYY-MM-DD
      

      关于java.time

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

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

      要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

      从哪里获得 java.time 类?

      ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-09-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-24
        相关资源
        最近更新 更多