对于信用卡/借记卡的过期日期,我使用的数组包含2020年至2030年以来的所有年份:
String[] expirationYearArray = { "2020", "2021", "2022", "2023", "2024", "2025", "2026", "2027", "2028", "2029", "2030" };这是个糟糕的方法,因为年数是硬编码的。这意味着3年后,即2023年,用户仍然可以选择2020、2021和2022年作为信用卡的到期日期。这显然是错误的。我想要做的是用字符串填充数组,从当前年份到当前年份再多10年。我想要做的是使用Java内置函数来获得当前的年份。然后使用for循环进行10次迭代,在每次迭代中从Int转换为String,以便我将2020转换为"2020",然后将该"2020"作为expirationYearArray数组的第一个元素。for或while循环将继续这样做,直到我到达第十次迭代为止。这种方法对你有意义吗?请让我知道,如果你看到了一个不同的或更好的选择,可能会做同样的用较少的代码,如果这对你有意义的方式,我的设想。谢谢。
发布于 2020-03-10 19:46:21
以下是几种变体:
public static void main(String[] args) {
System.out.println(Arrays.toString(getExpirationYears(LocalDateTime.now().getYear())));
System.out.println(Arrays.toString(getExpirationYears(Calendar.getInstance().get(Calendar.YEAR))));
System.out.println(Arrays.toString(getExpirationYears(1900 + new Date().getYear())));
System.out.println(Arrays.toString(getExpirationYearByStreams(1900 + new Date().getYear())));
}
static String[] getExpirationYears(int year) {
String[] expirationYearArray = new String[10];
for (int i = 0; i < expirationYearArray.length; i++) {
expirationYearArray[i] = String.valueOf(year + i);
}
return expirationYearArray;
}
static String[] getExpirationYearByStreams(int year) {
return IntStream.range(year, year+10)
.boxed()
.map(String::valueOf)
.toArray(String[]::new);
}发布于 2020-03-10 19:56:10
tl;dr
2行,使用流和lambda语法。
Year currentYear = Year.now( ZoneId.of( "Pacific/Auckland" ) ); // Determining the current year requires a time zone when near the ending/beginning of the year.
List < Year > years = // A list of objects of the class `Year`. Better to use a specific type than use a mere integer number.
IntStream // Generates a stream of `int` primitive numbers.
.range( // Get numbers from the specified beginning to the specified ending.
currentYear.getValue() , // Get `int` number of the current year.
currentYear.plusYears( 10 ).getValue() // Yet the `int` number of a later year.
) // Returns a `IntStream` object.
.boxed() // Converts the `int` primitive values into a stream of `Integer` objects.
.map( integer -> Year.of( integer ) ) // Uses each `Integer` object to instantiate a `Year` object. The `Integer` object is auto-boxed back into an `int` primitive`. Primitives cannot be mapped in a stream with a lambda. So we had to do this funky `int` -> `Integer` -> `int` conversion juggling.
.collect( Collectors.toList() ) // Gather the `Year` objects produced by the `map` method into a `List` collection.
;在几行中,使用常规语法。
Year currentYear = Year.now( ZoneId.of( "Asia/Tokyo" ) ) ;
List< Year > years = new ArrayList<>( 10 ) ;
for( int i = 0 ; i < 10 ; i ++ )
{
years.add( currentYear.plusYears( i ) ) ;
}years.toString():2020年,2021,2022年,2023年,2024年,2025年,2026年,2027年,2028年,2029年
java.time.Year
Java提供了一个特定的类来表示一年,恰当地命名为Year。我建议使用这个类而不是一个整数来使您的代码类型更加安全和更自文档化。
时区是至关重要的
获取当前年份需要一个时区。在任何特定的时刻,世界各地的日期按时区不同。“明天”在日本东京,同时也是“昨天”在魁北克蒙特勒亚省。
因此,大约在一年的最后一天/第一天,可能是“明年”在日本东京,同时“去年”在魁北克蒙特勒阿省。因此,在确定当前年份时,请指定所需/预期的时区。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
Year currentYear = Year.now( z ) ;通过迭代获得你的下一个十年。
List< Year > years = new ArrayList<>( 10 ) ;
Year year = currentYear ;
for( int i = 0 ; i < 10 ; i ++ )
{
// Remember this year.
years.add( year ) ;
// Set up the next loop.
year = currentYear.plusYears( i ) ;
}通过调用不可修改的列表从该ArrayList生成List.copyOf。
List< Year > years = List.copyOf( years ) ; // Returns an unmodifiable `List`, with adding/removing elements disallowed.java.time.Month
对于到期年份-月份,您还需要一个小部件来选择月份.在那里,您可以使用Month类。
List< Month > months = List.copyOf( Month.values() ) toString方法的Month根据枚举元素的名称以所有大写字母给出月份的名称。您可能需要将本地化的名称列表显示给用户。
List< String > monthsLocalized = new ArrayList<>( months.size() ) ;
Locale locale = Locale.CANADA_FRENCH ;
for( Month month : months )
{
monthsLocalized.add( month.getDisplayName( TextStyle.FULL , locale ) ;
}
monthsLocalized = List.copyOf( monthsLocalized ) ;java.time.YearMonth
对于用户选择一年零一个月的最终结果,请使用YearMonth。奇怪的是,YearMonth工厂方法不接受Year对象,而只是一个整数。所以打电话给Year::getValue得到电话号码。
YearMonth yearMonth = YearMonth.of( selectedYear.getValue() , selectedMonth ) ;早熟优化
您对优化性能表示了关注。这不是您需要优化的代码类型。的确,不要落入过早优化的陷阱。即使是最有经验的程序员也被证明是出了名的不善于凭直觉猜测瓶颈在他们的代码库中的位置。只有在经历了显著的影响代码性能和业务运行的重大减速之后才进行优化。最常见的情况是,编写简单、直截了当的Java代码行将导致在Java编译器和运行时优化器(HotSpot,OpenJ9)完成任务后执行高度优化的代码。
关于java.time
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/package-summary.html框架内置到Java8和更高版本中。这些类取代了麻烦的旧遗赠日期时间类,如java.util.Date、Calendar和SimpleDateFormat。
要了解更多信息,请参见http://docs.oracle.com/javase/tutorial/datetime/TOC.html。并搜索堆栈溢出以获得许多示例和解释。规范是JSR 310。
http://www.joda.org/joda-time/项目现在在维护模式中,建议迁移到java.time类。
您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC 4.2。不需要字符串,也不需要java.sql.*类。
在哪里获得java.time类?
发布于 2020-03-10 20:03:20
避免对年表进行硬编码是个好主意。
至于您生成的年份范围,您可以向您的卡处理器查询规则。例如,在某些情况下,过期卡可以在设置定期收费时收取费用,比如订阅,但它们可能不应该被接受为新计划。同样,信用卡通常在10年前到期;您的处理器可能会拒绝过期时间过长的信用卡。
同样,处理器在时区的强制执行方面可能不一致。有些人可能会考虑一年结束,当它结束在他们的本地时区,其他人可能使用世界协调时。最宽松的策略是使用来自UTC的偏移量为-12:00的“地球上的任何地方”地带,。
要使您的逻辑可测试,请将它传递给一个Clock实例。通常,时钟将是系统默认时钟,但在这种情况下,您可能会将区域设置为“世界上的任何地方”。通过传递时钟,您可以消除对实际时间的依赖,并测试计算在任何时候的行为。
private static final ZoneOffset aoe = ZoneOffset.ofHours(-12);
private static final DateTimeFormatter fmt = DateTimeFormatter.ofPattern("uuuu");
public static void main(String[] args) {
Clock clock = Clock.system(aoe);
List<Year> years = nextYears(clock, 10L);
years.stream().map(fmt::format).forEach(System.out::println);
}
private List<Year> nextYears(Clock clock, long count) {
return Stream.iterate(Year.now(clock), year -> year.plusYears(1L))
.limit(count)
.collect(Collectors.toList());
}https://stackoverflow.com/questions/60624102
复制相似问题