Массив строк, содержащий количество лет с истекшим сроком действия кредитной карты, начиная с текущего года, еще 10 лет - PullRequest
2 голосов
/ 10 марта 2020

Для даты истечения срока действия кредитных / дебетовых карт я использую массив, содержащий все годы с 2020 по 2030 год:

String[] expirationYearArray = { "2020", "2021", "2022", "2023", "2024", "2025", "2026", "2027", "2028", "2029", "2030" };

Это плохой подход, поскольку годы жестко запрограммированы. Это означает, что через 3 года, в 2023 году, пользователи по-прежнему будут иметь возможность выбрать 2020, 2021 и 2022 год в качестве даты истечения срока действия кредитных карт. Это явно неправильно. Что я хочу сделать, это заполнить массив строками из текущего года и еще 10 лет из текущего года. То, что я думаю сделать, это использовать встроенную функцию Java, чтобы получить текущий год. Затем используйте для l oop, чтобы сделать 10 итераций, и в каждой итерации конвертировать из Int в String, чтобы я преобразовал 2020 в "2020", а затем pu sh, что "2020", в качестве первого элемента expirationYearArray массив. For или while l oop будет продолжать делать это, пока я не достигну десятой итерации. Имеет ли этот подход смысл для вас? Пожалуйста, дайте мне знать, если вы видите другой или более оптимальный вариант, который может сделать то же самое с меньшим количеством кода, или если это имеет смысл для вас так, как я это представляю. Спасибо.

Ответы [ 4 ]

2 голосов
/ 10 марта 2020

tl; dr

В 2 строки, используя потоки и лямбда-синтаксис.

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 ) ) ;
}

См. этот код запускается на IdeOne.com .

years.toString (): [2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029 ]

java.time.Year

Java предлагает определенный класс c для представления года с соответствующим именем Year. Я предлагаю использовать этот класс, а не просто целое число, чтобы сделать ваш код безопасным для типов и более самодокументируемым.

Часовой пояс имеет решающее значение

Для получения текущего года требуется часовой пояс. На любой данный момент даты различны по всему миру по часовым поясам. Хотя «завтра» в Токио, Япония, это одновременно «вчера» в Монреале-Квебе c.

Следовательно, примерно в последний день / первый день года это может быть "следующий год" в Токио, Япония, и одновременно "последний год" в Монреале-Квебе c. Поэтому при определении текущего года укажите желаемый / ожидаемый часовой пояс.

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() ) 

Метод Month toString дает название месяца на английском языке sh в верхнем регистре на основе имени элемента enum. Возможно, вы захотите составить список локализованных имен для отображения пользователям.

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) выполнят свою работу.

About java .time

Фреймворк java .time встроен в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Чтобы узнать больше, см. Учебник Oracle . И поиск переполнения стека для многих примеров и объяснений. Спецификация: JSR 310 .

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на java .time классы.

Вы можете обмениваться java .time объектами напрямую с вашей базой данных. Используйте драйвер JDB C , совместимый с JDB C 4.2 или более поздней версией. Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где взять классы java .time?

  • Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11 и более поздних версий - часть стандартного API Java со связанной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть java. время функциональность перенесена на Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии Android связывают реализации классов java .time .
    • Для более ранних версий Android (<26) проект <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP адаптируется ThreeTen-Backport (упомянуто выше). См. Как использовать ThreeTenABP… .
2 голосов
/ 10 марта 2020

Это хорошая идея, чтобы избежать жесткого кодирования списка лет.

Что касается периода, который вы генерируете, вы можете узнать у вашего процессора карты правила. Например, карты с истекшим сроком действия могут взиматься в некоторых случаях, когда они были настроены на регулярную оплату, например, по подписке, но они, вероятно, не должны приниматься для новых планов. Аналогичным образом срок действия кредитных карт обычно истекает раньше, чем через 10 лет; Ваш процессор может отклонять карты с нереально долгим сроком действия.

Опять же, процессоры могут быть непоследовательны в применении часовых поясов. Некоторые могут считать, что год заканчивается, когда он заканчивается в местном часовом поясе, другие могут использовать UT C. Наиболее мягким правилом будет использование зоны "где угодно на земле", со смещением -12: 00 от UT C.

, чтобы сделать вашу логику c тестируемой , передайте ему экземпляр 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());
}
1 голос
/ 10 марта 2020

Вот несколько вариантов:

  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);

}
0 голосов
/ 11 марта 2020

Вот как я добился этого в своем коде, следуя совету Ноники (см. Его ответ):

package com.myapp;
..........
public class Payment extends BaseActivity implements ResponseListener {
    ..........
    int currentYear = Calendar.getInstance().get(Calendar.YEAR);
    String[] cardYearArray = new String[10];
    ..........
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ..........
        cardYearArray=getExpirationYears(currentYear);
        SpinnerAdapter creditCardYearAdapter = new SpinnerAdapter(Payment.this,
            cardYearArray);
        ..........
    }
    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;
    }
    ..........
}

Теперь я вижу правильные годы, когда мне это нужно:

enter image description here

...