【问题标题】:Java replace part of the string before a commaJava替换逗号前的部分字符串
【发布时间】:2017-04-06 18:12:50
【问题描述】:

我有一个数据格式的字符串,apr 17,2016

例如,我想返回 1 天,所以我想得到apr 16,2016

我该怎么做?

请注意,它也可能是mar 1,2016,因此索引处的替换不起作用。

【问题讨论】:

  • 您将值解析为日期/时间(例如使用java.time),然后使用适当的日期操作方法。您不要尝试使用字符串操作来完成所有操作。
  • 我把它作为一个字符串,所以我必须使用它。 (测试自动化目的,不是开发。不清楚,但没关系,我的问题是准确的)
  • 你必须使用它,当然。这就是“你解析值”部分的内容。这并不意味着您必须使用字符串操作来做所有事情。 (这就是当前的两个答案所做的,这是一个非常糟糕的主意。当 Java 中已经有多种解析日期的方法时,为什么还要重新发明轮子?)
  • 我需要检查一下,我对java.time不熟悉。谢谢。你认为它比字符串操作更容易吗?我总是会得到字符串,我需要解析值,反之亦然,最后也得到一个字符串。是不是很贵?
  • 你有明确定义的性能限制吗?你还没有提到那些。我肯定会从尝试在适当域中工作的简单、清晰的代码开始 - “获取前一天”肯定是在日期/时间域而不是字符串域中工作。

标签: java string replace substring


【解决方案1】:

tl;博士

LocalDate.parse ( 
    "apr 17,2016" , 
    DateTimeFormatter.ofPattern ( "MMM dd,uuuu" ).withLocale( locale ) 
)

使用 java.time

现代方式是使用java.time 类。

您没有为输入字符串指定区域设置或人类语言。月份名称缩写中的首字母小写不适合美国英语。所以我尝试了 Java 8 Update 121 提供的所有语言环境,忽略了任何因异常而失败的解析尝试。

注意我们如何在循环中调用DateTimeFormatter::withLocaleLocale 确定 (a) 用于翻译日期名称、月份名称等的人类语言,以及 (b) 决定缩写、大写、标点符号、分隔符等问题的文化规范。

您可以通过调用LocalDate::minusDays 进行日期时间数学运算以获取前一天。

String input = "apr 17,2016";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "MMM dd,uuuu" );

for ( Locale locale : Locale.getAvailableLocales ( ) ) {
    try {
        LocalDate ld = LocalDate.parse ( input, f.withLocale ( locale ) );
        System.out.println ( locale.getDisplayName ( ) + " → " + ld + " | day before: " + ld.minusDays ( 1 ) );
    } catch ( java.time.format.DateTimeParseException e ) {
        // Swallow this expected exception. No code needed here.
    }
}
System.out.println ( "Done." );

十九个工作。

Italian → 2016-04-17 | day before: 2016-04-16
Swedish (Sweden) → 2016-04-17 | day before: 2016-04-16
Slovak → 2016-04-17 | day before: 2016-04-16
Estonian → 2016-04-17 | day before: 2016-04-16
Swedish → 2016-04-17 | day before: 2016-04-16
Serbian (Latin,Bosnia and Herzegovina) → 2016-04-17 | day before: 2016-04-16
Serbian (Latin,Montenegro) → 2016-04-17 | day before: 2016-04-16
Norwegian (Norway,Nynorsk) → 2016-04-17 | day before: 2016-04-16
Estonian (Estonia) → 2016-04-17 | day before: 2016-04-16
Serbian (Latin) → 2016-04-17 | day before: 2016-04-16
Dutch → 2016-04-17 | day before: 2016-04-16
Norwegian (Norway) → 2016-04-17 | day before: 2016-04-16
Dutch (Netherlands) → 2016-04-17 | day before: 2016-04-16
Italian (Switzerland) → 2016-04-17 | day before: 2016-04-16
Slovak (Slovakia) → 2016-04-17 | day before: 2016-04-16
Italian (Italy) → 2016-04-17 | day before: 2016-04-16
Dutch (Belgium) → 2016-04-17 | day before: 2016-04-16
Norwegian → 2016-04-17 | day before: 2016-04-16
Serbian (Latin,Serbia) → 2016-04-17 | day before: 2016-04-16
Done.

关于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

【讨论】:

    【解决方案2】:

    您可以为此使用 Java 8

    只需转换为LocalDate。出于多种原因,它具有灵活的 API。

    这里是代码sn-p:

    public static void main(String[] args) throws ParseException {
        String dateStr = "apr 17,2016";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd,uuuu");
    
        // convert to local date
        LocalDate localDate = LocalDate.parse(dateStr, formatter.withLocale(Locale.ITALIAN));
        System.out.println("START DATE:\n" + localDate);
    
        // use all power of new java.time
        LocalDate oneDayBefore = localDate.minusDays(1);
        LocalDate oneMonthBefore = localDate.minusMonths(1);
        LocalDate oneWeekBefore = localDate.minusWeeks(1);
        LocalDate oneYearBefore = localDate.minusYears(1);
    
        System.out.println("RESULTS:");
        System.out.println(oneDayBefore);
        System.out.println(oneMonthBefore);
        System.out.println(oneWeekBefore);
        System.out.println(oneYearBefore);
    }
    

    输出:

    START DATE:
    2016-04-17
    RESULTS:
    2016-04-16
    2016-03-17
    2016-04-10
    2015-04-17
    

    现在您需要将本地日期打印为字符串。

    示例如下:

        // use Java 8 features
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MMM dd,yyyy");
        String dt = dtf.format(oneDayBefore);
        System.out.println(dt);
    

    输出:

    Apr 16,2016
    

    【讨论】:

    • 如果您使用 LocalDate - 我同意这是正确的方式 - 不要使用 SimpleDateFormat... 使用 DateTimeFormatter... 这就是它的用途。跨度>
    • 正如 Jon Skeet 评论的那样,您正在混合不兼容的类。 java.time 类取代了旧的日期时间类。仅使用 java.time 类。此外,您正在过度解决问题。仅使用 LocalDate 而无需转到日期时间 (Instant)。
    • @JonSkeet 感谢您的推荐。答案已更新。
    • 万岁——好多了。最后一个我可以完全支持的答案:)(诚然,我不确定将语言环境设置为意大利语 - 但至少它是明确的。希望 OP 将其设置为他们真正想要的任何内容。)
    • 谢谢大家的帮助!请注意,我接受了一种解决方案,但我敢肯定,其他解决方案运行良好。我需要一个简单的解决方案,我发现它很有帮助。再次感谢!
    【解决方案3】:

    **注意:你应该使用日期类而不是字符串,但是有比我在这里使用的更好的类。 ** 我将编辑此答案以反映这一点,但您应该在下面查看更适合当前 Java 版本以及此处要求的精度(天而不是毫秒)的解决方案。

    最可靠的方法是将字符串转换为日期类,操作日期,然后重新格式化。各个方向的转换可以通过 SimpleDateFormat 类 (Api docs) 完成,日期的更改可以通过 Calendar 类轻松完成 (API docs)

    这运行并从参数中获取日期,并按照您的要求输出减去一天的格式。

    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Calendar;
    
    public class DateSubtractExample{
        public static String backOneDay(String inDate){
          SimpleDateFormat formatter = new SimpleDateFormat("MMM dd,yyyy");
          try{
              // turn your string into a date (if formatting is right)
              Date date1 = formatter.parse(inDate);
              // make a calendar, set it to the date, and subtract one day.
              Calendar cal = Calendar.getInstance();
              cal.setTime(date1);
              cal.add(Calendar.DATE,-1);
              // convert date back to input format. 
              return formatter.format(cal.getTime());
            }
            catch (ParseException bad){
                    bad.printStackTrace();
                    return "UNREADABLE DATE "+inDate+":"+bad;
    
            }
        }
    
        public static void main(String[] args) throws ParseException{
           System.out.println(DateSubtractExample.backOneDay(args[0]));
        }
    }
    

    【讨论】:

    • 这绝对比原始字符串操作好,但我建议这些天尽可能使用java.time
    • 支持@JonSkeet 的评论,Date 是一个毫秒精度的时间点,这基本上不是你需要的。 LocalDate in java.time 更好地反映(模型)你所追求的(有几个其他答案使用它)。
    【解决方案4】:
    public String getPreviousDate(String oldDate) {
        String[] parts1 = oldDate.split(" "); // split the oldDate around " "
        String[] parts2 = parts1[1].split(","); // split the second part of oldDate around ","
    
        String month = parts1[0];
        int day = Integer.parseInt(parts2[0]);
        int year = Integer.parseInt(parts2[1]);
        ...
        return newDate;
    }
    

    【讨论】:

    • 您似乎在此处的“...”中省略了很多...例如计算现在是几月,结果中应该是几月。我还强烈建议反对编写你自己的日期解析器,这实际上就是你正在做的事情。
    【解决方案5】:

    这将根据您的要求工作,请试试这个,经过测试的程序,所以不用担心

    import java.text.SimpleDateFormat;  
    import java.util.*;
    
    public class DateExample{
        public static void main(String args[]) throws Exception {
    
            String date = "apr 16,2016";
        SimpleDateFormat formatter=new SimpleDateFormat("MMM dd,yyyy");  
    
        Date dateFormated =formatter.parse(date);  
        System.out.println(dateFormated);
    
        GregorianCalendar cal = new GregorianCalendar();
        cal.setTime(dateFormated);
        cal.add(Calendar.DATE, -1);
    
            Date newDate = cal.getTime();
        String stringDate = formatter.format(newDate);
            System.out.println(stringDate);
        }
    
    }
    

    【讨论】:

    • 请注意,这将使用系统默认区域设置,这可能不是一个好主意 - 如果已知这些值位于特定区域设置中,那就应该使用它。
    【解决方案6】:

    我觉得你问的问题我不清楚。我看到了两个问题,一个与替换部分字符串有关,另一个与日期有关。我想你的问题是关于日期的。因此,我试图回答您的问题,认为您想将当前日期减少一天。

    为此,您可以使用日历界面。

    Calendar cal = Calendar.getInstance();
    cal.setTime(myDate);
    cal.add(Calendar.DAY_OF_YEAR,-1);
    Date oneDayBefore= cal.getTime();
    

    【讨论】:

      【解决方案7】:

      所以,我使用 string.split(",")。 示例代码:

      String date="apr 1,2016";
      String[] parts=date.split(",");
      String month_and_day=parts[0];
      String year=parts[1];
      String[] parts_of_month_and_day=month_and_day.split(" ");
      String month=parts_of_month_and_day[0];
      String day=parts_of_month_and_day[1];
      int m;
      int d;
      int y;
      y=Integer.parseInt(year);
      d=Integer.parseInt(day);
      String[] months=new String[] {"jan","feb","mar","apr","may","jun","jul","aug","sep","okt","nov","dez"};
      for (int i=0; i < 12 /*length of months*/; i++) {
           if (months[i].equals(month)) {
               m=i;
           }
      }
      

      【讨论】:

      • 您为什么要使用String.split 而不是使用各种解析日期的方法中的任何一种?您似乎很乐意使用Integer.parseInt - 那么为什么不使用日期解析工具呢?
      • 请注意,您也只完成了一半的工作。您已经编写了一些解析代码,但没有减去一天并重新格式化。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-28
      • 1970-01-01
      • 2011-12-23
      • 2010-12-31
      • 2013-09-20
      • 1970-01-01
      • 2020-02-24
      相关资源
      最近更新 更多