如何在Scala中获取上一年的相应季度
How to get corresponding quarter of previous year in Scala
我有一个格式为“20202”[“yyyyQ”] 的日期字符串。有没有办法得到上一年对应的季度?
ex- 20202 应该是 20192
这是一个简短的 Scastie 展示了一种方法。
val d = "20202"
(d.substring(0,4).toInt - 1).toString + d.substring(4) // 20192: String
更新(感谢 )
下面给出的是纯粹的DateTimeFormatter
解决方案:
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.IsoFields;
import org.threeten.extra.YearQuarter;
public class Main {
public static void main(String[] args) {
// Given string
String str = "20202";
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4)
.appendValue(IsoFields.QUARTER_OF_YEAR, 1)
.toFormatter();
// Parse the converted string
YearQuarter yearQuarter = YearQuarter.parse(str, dtf);
System.out.println(yearQuarter.format(dtf));
// A year ago
System.out.println(yearQuarter.minusYears(1).format(dtf));
}
}
输出:
20202
20192
原回答:
我建议您使用 ThreeTenExtra 库。您必须处理的唯一问题是将给定的字符串转换为 yyyy-Q
格式,您可以使用正则表达式轻松完成此操作,如下所示:
import java.time.format.DateTimeFormatter;
import org.threeten.extra.YearQuarter;
public class Main {
public static void main(String[] args) {
// Given string
String str = "20202";
// Convert the given string into yyyy-Q format
str = str.replaceAll("(\d{4})(\d{1,2})", "-");
// Parse the converted string
YearQuarter yearQuarter = YearQuarter.parse(str, DateTimeFormatter.ofPattern("yyyy-Q"));
// Define output format
DateTimeFormatter outputFormat = DateTimeFormatter.ofPattern("uuuuQ");
System.out.println(yearQuarter.format(outputFormat));
// A year ago
System.out.println(yearQuarter.minusYears(1).format(outputFormat));
}
}
输出:
20202
20192
正则表达式的解释:
(\d{4})(\d{1,2})
指定两组:第一组有 4 个数字,第二组有一个或两个数字
- 替换字符串
-
指定group(1)-group(2)
I thought of using some Date time formatter to solve this, …
做!我会立即更喜欢 Arvind Kumar Avinash 使用 ThreeTen Extra 库的 YearQuarter
的解决方案。如果您发现将外部库添加到您的项目(或者您的团队或老板这么认为)是多余的,我们也可以不用它,只是不太优雅。这是一个 Java 解决方案,我认为您可以将其翻译成 Scala:
DateTimeFormatter quarterFormatter = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4)
.appendValue(IsoFields.QUARTER_OF_YEAR, 1)
.parseDefaulting(IsoFields.DAY_OF_QUARTER, 1)
.toFormatter();
String quarterString = "20202";
YearMonth firstMonthOfQuarter
= YearMonth.parse(quarterString, quarterFormatter);
YearMonth firstMonthOfQuarterLastYear = firstMonthOfQuarter.minusYears(1);
String quarterPreviousYearString
= firstMonthOfQuarterLastYear.format(quarterFormatter);
System.out.println(quarterPreviousYearString);
输出是期望的:
20192
正确数据类型的优点
Could you please explain what advantages usage of DateTime may have in
this case over simple string manipulation and conversion to int?
编辑:当您需要从输入中读取一些数字(例如 ID 号)并在输出中再次打印时,您是将其读入 int
还是 String
?大多数使用int
(或long
或BigInteger
)。为什么?你的问题类似。
使用 YearQuarter
或 YearMonth
的优势包括(可能不限于):
- Self-explanatory 代码:
val d = "20202"
并没有说明这段数据的含义。 YearQuarter
类型的变量非常清楚地告诉 reader 这个变量保存一年的四分之一。 YearMonth
是标准 Java 库中的最佳近似值,并且已经不太清楚为什么我们在这里使用它,但仍然比 String
. 有很大的优势
- 免费验证: 通过使用格式化程序解析字符串,如果字符串不表示有效的季度,我们一定会通过异常得到通知.
- 进一步验证便宜:如果您想要进一步验证,例如该季度必须在 2019 年第二季度之后,但不能在未来,这很简单直接 java.time(它也可以用字符串来完成,但是代码将很难阅读,除非你用几行注释解释你要做什么)。
- 为未来的需求做好准备:如果有一天你需要对这个季度做更多的事情,比如找到这个季度的第一天和最后一天或前一个季度它,这将是在公园散步,因为 class 提供了一组非常丰富的操作。
Link
Oracle tutorial: Date Time 解释如何使用 java.time.
其他答案的替代方法是使用我的库 Time4J and its class CalendarQuarter。示例:
String input = "20202";
ChronoFormatter<CalendarQuarter> f =
ChronoFormatter.ofPattern(
"yyyyQ",
PatternType.CLDR,
Locale.ENGLISH,
CalendarQuarter.chronology());
CalendarQuarter cq = f.parse(input);
CalendarQuarter quarterInPreviousYear = cq.minus(Years.ONE);
System.out.println(quarterInPreviousYear); // 2019-Q2
此解决方案的两个主要优点是:
- 日历季度也是间隔,因此很容易每天对其进行迭代。
- 支持 90 多种语言的国际化,甚至 style-based。
间隔示例:
for (PlainDate date : quarterInPreviousYear) {
System.out.println(date);
}
输出:
> 2019-04-01
> 2019-04-02
> 2019-04-03
> ...
丹麦语打印示例:
ChronoFormatter<CalendarQuarter> printer =
ChronoFormatter.ofPattern(
"QQQQ y",
PatternType.CLDR,
new Locale("da"),
CalendarQuarter.chronology());
System.out.println(printer.print(quarterInPreviousYear)); // 2. kvartal 2019
我有一个格式为“20202”[“yyyyQ”] 的日期字符串。有没有办法得到上一年对应的季度?
ex- 20202 应该是 20192
这是一个简短的 Scastie 展示了一种方法。
val d = "20202"
(d.substring(0,4).toInt - 1).toString + d.substring(4) // 20192: String
更新(感谢 )
下面给出的是纯粹的DateTimeFormatter
解决方案:
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.IsoFields;
import org.threeten.extra.YearQuarter;
public class Main {
public static void main(String[] args) {
// Given string
String str = "20202";
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4)
.appendValue(IsoFields.QUARTER_OF_YEAR, 1)
.toFormatter();
// Parse the converted string
YearQuarter yearQuarter = YearQuarter.parse(str, dtf);
System.out.println(yearQuarter.format(dtf));
// A year ago
System.out.println(yearQuarter.minusYears(1).format(dtf));
}
}
输出:
20202
20192
原回答:
我建议您使用 ThreeTenExtra 库。您必须处理的唯一问题是将给定的字符串转换为 yyyy-Q
格式,您可以使用正则表达式轻松完成此操作,如下所示:
import java.time.format.DateTimeFormatter;
import org.threeten.extra.YearQuarter;
public class Main {
public static void main(String[] args) {
// Given string
String str = "20202";
// Convert the given string into yyyy-Q format
str = str.replaceAll("(\d{4})(\d{1,2})", "-");
// Parse the converted string
YearQuarter yearQuarter = YearQuarter.parse(str, DateTimeFormatter.ofPattern("yyyy-Q"));
// Define output format
DateTimeFormatter outputFormat = DateTimeFormatter.ofPattern("uuuuQ");
System.out.println(yearQuarter.format(outputFormat));
// A year ago
System.out.println(yearQuarter.minusYears(1).format(outputFormat));
}
}
输出:
20202
20192
正则表达式的解释:
(\d{4})(\d{1,2})
指定两组:第一组有 4 个数字,第二组有一个或两个数字- 替换字符串
-
指定group(1)-group(2)
I thought of using some Date time formatter to solve this, …
做!我会立即更喜欢 Arvind Kumar Avinash 使用 ThreeTen Extra 库的 YearQuarter
的解决方案。如果您发现将外部库添加到您的项目(或者您的团队或老板这么认为)是多余的,我们也可以不用它,只是不太优雅。这是一个 Java 解决方案,我认为您可以将其翻译成 Scala:
DateTimeFormatter quarterFormatter = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4)
.appendValue(IsoFields.QUARTER_OF_YEAR, 1)
.parseDefaulting(IsoFields.DAY_OF_QUARTER, 1)
.toFormatter();
String quarterString = "20202";
YearMonth firstMonthOfQuarter
= YearMonth.parse(quarterString, quarterFormatter);
YearMonth firstMonthOfQuarterLastYear = firstMonthOfQuarter.minusYears(1);
String quarterPreviousYearString
= firstMonthOfQuarterLastYear.format(quarterFormatter);
System.out.println(quarterPreviousYearString);
输出是期望的:
20192
正确数据类型的优点
Could you please explain what advantages usage of DateTime may have in this case over simple string manipulation and conversion to int?
编辑:当您需要从输入中读取一些数字(例如 ID 号)并在输出中再次打印时,您是将其读入 int
还是 String
?大多数使用int
(或long
或BigInteger
)。为什么?你的问题类似。
使用 YearQuarter
或 YearMonth
的优势包括(可能不限于):
- Self-explanatory 代码:
val d = "20202"
并没有说明这段数据的含义。YearQuarter
类型的变量非常清楚地告诉 reader 这个变量保存一年的四分之一。YearMonth
是标准 Java 库中的最佳近似值,并且已经不太清楚为什么我们在这里使用它,但仍然比String
. 有很大的优势
- 免费验证: 通过使用格式化程序解析字符串,如果字符串不表示有效的季度,我们一定会通过异常得到通知.
- 进一步验证便宜:如果您想要进一步验证,例如该季度必须在 2019 年第二季度之后,但不能在未来,这很简单直接 java.time(它也可以用字符串来完成,但是代码将很难阅读,除非你用几行注释解释你要做什么)。
- 为未来的需求做好准备:如果有一天你需要对这个季度做更多的事情,比如找到这个季度的第一天和最后一天或前一个季度它,这将是在公园散步,因为 class 提供了一组非常丰富的操作。
Link
Oracle tutorial: Date Time 解释如何使用 java.time.
其他答案的替代方法是使用我的库 Time4J and its class CalendarQuarter。示例:
String input = "20202";
ChronoFormatter<CalendarQuarter> f =
ChronoFormatter.ofPattern(
"yyyyQ",
PatternType.CLDR,
Locale.ENGLISH,
CalendarQuarter.chronology());
CalendarQuarter cq = f.parse(input);
CalendarQuarter quarterInPreviousYear = cq.minus(Years.ONE);
System.out.println(quarterInPreviousYear); // 2019-Q2
此解决方案的两个主要优点是:
- 日历季度也是间隔,因此很容易每天对其进行迭代。
- 支持 90 多种语言的国际化,甚至 style-based。
间隔示例:
for (PlainDate date : quarterInPreviousYear) {
System.out.println(date);
}
输出:
> 2019-04-01
> 2019-04-02
> 2019-04-03
> ...
丹麦语打印示例:
ChronoFormatter<CalendarQuarter> printer =
ChronoFormatter.ofPattern(
"QQQQ y",
PatternType.CLDR,
new Locale("da"),
CalendarQuarter.chronology());
System.out.println(printer.print(quarterInPreviousYear)); // 2. kvartal 2019