Java - 以日期格式交换月份和日期
Java - Swap Month & Day in Date Format
我有一个 String
日期格式(例如 dd/MM/yyyy)并希望以编程方式将其转换为美国格式,月份在前(例如 MM/dd/yyyy)。
这个用例是读取一些数据并确定最适合的格式。
这听起来很简单,但实际尝试实施后,我的解决方案似乎不是最优的。
以下是我的尝试,包括测试。
public class DateSwapperExample
{
private static final char dateFormatDayLetter = 'd', dateFormatMonthLetter = 'M';
/**
* Swaps the Day & Month component in a Date Format, if both are present <br>
* When swapping, ensures the frequency is retained - e.g. dd/MMM -> MMM/dd <br>
* TODO Only handles one instance of each tag <br>
* TODO This doesn't handle quoted elements in the Date Format (e.g. "dd/mm 'since dave made the best cakes' yyyy")
*/
private static String swapDayAndMonthInDateFormat(final String dateFormat)
{
// Get the position of the groups
final int[] dayIndex = new int[] {dateFormat.indexOf(dateFormatDayLetter), dateFormat.lastIndexOf(dateFormatDayLetter)};
final int[] monthIndex = new int[] {dateFormat.indexOf(dateFormatMonthLetter), dateFormat.lastIndexOf(dateFormatMonthLetter)};
if ((dayIndex[0] == -1) || (monthIndex[0] == -1))
{
// Cannot swap as dateFormat does not contain both dateFormatDayLetter & dateFormatMonthLetter
return dateFormat;
}
else
{
final int[] firstGroup, secondGroup;
// Work out which group comes first
if (dayIndex[0] < monthIndex[0])
{
firstGroup = dayIndex;
secondGroup = monthIndex;
}
else
{
firstGroup = monthIndex;
secondGroup = dayIndex;
}
// Split the string up into segments, re-organise and combine
// The other parts of the format at the start
return substringConstrained(dateFormat, 0, firstGroup[0])
// The second group
+ substringConstrained(dateFormat, secondGroup[0], secondGroup[1] + 1)
// The other parts of the format in the middle
+ substringConstrained(dateFormat, firstGroup[1] + 1, secondGroup[0])
// The first group
+ substringConstrained(dateFormat, firstGroup[0], firstGroup[1] + 1)
// The other parts of the format at the end
+ substringConstrained(dateFormat, secondGroup[1] + 1, dateFormat.length());
}
}
/** Extension of {@link String#substring(int, int)} that constrains the index parameters to be within the allowed range */
private static String substringConstrained(final String str, final int beginIndex, final int endIndex)
{
return str.substring(constrainToRange(beginIndex, 0, str.length()), constrainToRange(endIndex, 0, str.length()));
}
/** Copy of {@link com.google.common.primitives.Ints#constrainToRange(int, int, int)} to avoid the need of Guava in this example */
private static int constrainToRange(int value, int min, int max)
{
return Math.min(Math.max(value, min), max);
}
@org.junit.Test
public void testSwapDayAndMonthInDateFormat()
{
org.junit.Assert.assertEquals("Md", swapDayAndMonthInDateFormat("dM"));
org.junit.Assert.assertEquals("MMd", swapDayAndMonthInDateFormat("dMM"));
org.junit.Assert.assertEquals("Mdy", swapDayAndMonthInDateFormat("dMy"));
org.junit.Assert.assertEquals("Myd", swapDayAndMonthInDateFormat("dyM"));
org.junit.Assert.assertEquals("yMd", swapDayAndMonthInDateFormat("ydM"));
org.junit.Assert.assertEquals("aMbdc", swapDayAndMonthInDateFormat("adbMc"));
org.junit.Assert.assertEquals("MM/dd/yyyy", swapDayAndMonthInDateFormat("dd/MM/yyyy"));
org.junit.Assert.assertEquals("MMM/dd/yyyy", swapDayAndMonthInDateFormat("dd/MMM/yyyy"));
for (final String str : new String[] {"ydy", "yMy", "yDy", "ymy", "Dm", "Dmm", "DD/mm/yyyy", "DD/mmm/yyyy"})
{
org.junit.Assert.assertEquals(str, swapDayAndMonthInDateFormat(str));
}
}
}
private static String swapDayAndMonthInDateFormat(final String dateFormat)
{
return dateFormat.replaceFirst("(d+)(.*?)(M+)", "");
}
我完全不相信这是解决您实际问题的好方法。但它会让你测试通过。
另外你不应该使用 SimpleDateFormat
。 class 是出了名的麻烦,而且 Date
和朋友们早就过时了。而是使用 DateTimeFormatter
和来自 java.time 的其他 class,现代 Java 日期和时间 API。不过,格式模式字符串看起来仍然很相似,所以这个答案可能仍然相关。
我有一个 String
日期格式(例如 dd/MM/yyyy)并希望以编程方式将其转换为美国格式,月份在前(例如 MM/dd/yyyy)。
这个用例是读取一些数据并确定最适合的格式。
这听起来很简单,但实际尝试实施后,我的解决方案似乎不是最优的。
以下是我的尝试,包括测试。
public class DateSwapperExample
{
private static final char dateFormatDayLetter = 'd', dateFormatMonthLetter = 'M';
/**
* Swaps the Day & Month component in a Date Format, if both are present <br>
* When swapping, ensures the frequency is retained - e.g. dd/MMM -> MMM/dd <br>
* TODO Only handles one instance of each tag <br>
* TODO This doesn't handle quoted elements in the Date Format (e.g. "dd/mm 'since dave made the best cakes' yyyy")
*/
private static String swapDayAndMonthInDateFormat(final String dateFormat)
{
// Get the position of the groups
final int[] dayIndex = new int[] {dateFormat.indexOf(dateFormatDayLetter), dateFormat.lastIndexOf(dateFormatDayLetter)};
final int[] monthIndex = new int[] {dateFormat.indexOf(dateFormatMonthLetter), dateFormat.lastIndexOf(dateFormatMonthLetter)};
if ((dayIndex[0] == -1) || (monthIndex[0] == -1))
{
// Cannot swap as dateFormat does not contain both dateFormatDayLetter & dateFormatMonthLetter
return dateFormat;
}
else
{
final int[] firstGroup, secondGroup;
// Work out which group comes first
if (dayIndex[0] < monthIndex[0])
{
firstGroup = dayIndex;
secondGroup = monthIndex;
}
else
{
firstGroup = monthIndex;
secondGroup = dayIndex;
}
// Split the string up into segments, re-organise and combine
// The other parts of the format at the start
return substringConstrained(dateFormat, 0, firstGroup[0])
// The second group
+ substringConstrained(dateFormat, secondGroup[0], secondGroup[1] + 1)
// The other parts of the format in the middle
+ substringConstrained(dateFormat, firstGroup[1] + 1, secondGroup[0])
// The first group
+ substringConstrained(dateFormat, firstGroup[0], firstGroup[1] + 1)
// The other parts of the format at the end
+ substringConstrained(dateFormat, secondGroup[1] + 1, dateFormat.length());
}
}
/** Extension of {@link String#substring(int, int)} that constrains the index parameters to be within the allowed range */
private static String substringConstrained(final String str, final int beginIndex, final int endIndex)
{
return str.substring(constrainToRange(beginIndex, 0, str.length()), constrainToRange(endIndex, 0, str.length()));
}
/** Copy of {@link com.google.common.primitives.Ints#constrainToRange(int, int, int)} to avoid the need of Guava in this example */
private static int constrainToRange(int value, int min, int max)
{
return Math.min(Math.max(value, min), max);
}
@org.junit.Test
public void testSwapDayAndMonthInDateFormat()
{
org.junit.Assert.assertEquals("Md", swapDayAndMonthInDateFormat("dM"));
org.junit.Assert.assertEquals("MMd", swapDayAndMonthInDateFormat("dMM"));
org.junit.Assert.assertEquals("Mdy", swapDayAndMonthInDateFormat("dMy"));
org.junit.Assert.assertEquals("Myd", swapDayAndMonthInDateFormat("dyM"));
org.junit.Assert.assertEquals("yMd", swapDayAndMonthInDateFormat("ydM"));
org.junit.Assert.assertEquals("aMbdc", swapDayAndMonthInDateFormat("adbMc"));
org.junit.Assert.assertEquals("MM/dd/yyyy", swapDayAndMonthInDateFormat("dd/MM/yyyy"));
org.junit.Assert.assertEquals("MMM/dd/yyyy", swapDayAndMonthInDateFormat("dd/MMM/yyyy"));
for (final String str : new String[] {"ydy", "yMy", "yDy", "ymy", "Dm", "Dmm", "DD/mm/yyyy", "DD/mmm/yyyy"})
{
org.junit.Assert.assertEquals(str, swapDayAndMonthInDateFormat(str));
}
}
}
private static String swapDayAndMonthInDateFormat(final String dateFormat)
{
return dateFormat.replaceFirst("(d+)(.*?)(M+)", "");
}
我完全不相信这是解决您实际问题的好方法。但它会让你测试通过。
另外你不应该使用 SimpleDateFormat
。 class 是出了名的麻烦,而且 Date
和朋友们早就过时了。而是使用 DateTimeFormatter
和来自 java.time 的其他 class,现代 Java 日期和时间 API。不过,格式模式字符串看起来仍然很相似,所以这个答案可能仍然相关。