Как вычистить дату рождения в Java случайным образом, что приводит к тому же случайному числу, генерируемому, когда я кормлю ту же самую оригинальную дату рождения - PullRequest
1 голос
/ 07 октября 2019

Я пытаюсь выполнить очистку данных, когда я пытаюсь очистить поле даты рождения, но я хочу, чтобы оно было таким, чтобы одно и то же случайное число или дата рождения генерировались для одной и той же входной даты. Пожалуйста, помогите мне в этом.

Я пробовал этот случайный код генерации, но он генерирует другой код, даже если я предоставляю тот же ввод. Я хочу, чтобы случайный вывод оставался неизменным.

import java.util.GregorianCalendar;

public class RandomDateOfBirth {

    public static void main(String[] args) {
        GregorianCalendar gc = new GregorianCalendar();
        int year = randBetween(1900, 2010);
        gc.set(gc.YEAR, year);
        int dayOfYear = randBetween(1, gc.getActualMaximum(gc.DAY_OF_YEAR));
        gc.set(gc.DAY_OF_YEAR, dayOfYear);
        System.out.println(gc.get(gc.YEAR) + "-" + (gc.get(gc.MONTH) + 1) + "-" + gc.get(gc.DAY_OF_MONTH));
    }

    public static int randBetween(int start, int end) {
        return start + (int) Math.round(Math.random() * (end - start));
    }

}

Ответы [ 3 ]

1 голос
/ 08 октября 2019

Осторожно: если вы заменяете конфиденциальную часть данных значением, которое можно многократно определять, вы на самом деле не удалили свои данные. Если ваша цель - защитить конфиденциальные данные, такие как HIPAA , я советую вам проконсультироваться с ответственным лицом. Они должны быть обучены тому, как правильно очищать данные.

Еще один момент, который необходимо уточнить: ваш заголовок является сокращением. Случайное значение не может быть предсказуемо повторено по определению.

java.time

Ваш пример кода использует ужасные классы даты и времени, которые были вытеснены годами назад современными java.time классы, определенные в JSR 310. Для значения только на дату используйте LocalDate class.

Просто назначьте произвольное количество дней

Если вы хотите произвольную, но повторяемую корректировку, просто добавьте или вычтите определенное количество дней. Вы можете произвольно назначить отрицательное число (вычитание) для даты, чей номер дня является нечетным, и назначить положительное число (сложение) для даты, чей номер дня является четным.

Чтобы определить четное или нечетное число, см. этот вопрос .

int daysToAddToOddDayNumber = -2_555 ;
int daysToAddToEvenDayNumber = 2_101 ; 

LocalDate localDate = LocalDate.of( 1970 , Month.JANUARY , 1 );
boolean isEven = ( ( localDate.getDayOfMonth() & 1) == 0 ) ;
LocalDate adjusted = isEven ? localDate.plusDays( daysToAddToEvenDayNumber ) : localDate.plusDays( daysToAddToOddDayNumber ) ;

Дамп на консоль.

System.out.println( "localDate.toString(): " + localDate ) ;
System.out.println( "adjusted.toString(): " + adjusted ) ;

См. код запускается в режиме реального времени на IdeOne.com.

localDate.toString (): 1970-01-01

Adjust.toString (): 1963-01-03

Неизвестно, сколько дней будет добавлено

Вы можете немного поумнеть, взяв хэш значения даты, а затем используйте этот результат, чтобы определить количество дней длябыть добавленнымОпять же, как я уже говорил, это не может считаться достаточной очисткой в ​​зависимости от потребностей (и законов!) Вашего проекта.

LocalDate localDate = LocalDate.of( 1970 , Month.JANUARY , 1 );
String input = localDate.toString();

MessageDigest md = null;
try
{
    md = MessageDigest.getInstance( "MD5" );
    md.update( input.getBytes() );
    byte[] digest = md.digest();
    int days = new BigInteger( 1 , digest ).mod( new BigInteger( "10000" ) ).intValue();
    LocalDate adjusted = localDate.minusDays( days );

    System.out.println( "localDate = " + localDate );
    System.out.println( "input = " + input );
    System.out.println( "days = " + days );
    System.out.println( "adjusted = " + adjusted );
} catch ( NoSuchAlgorithmException e )
{
    e.printStackTrace();
}

См. Этот код, запущенный на IdeOne.com.

localDate = 1970-01-01

input = 1970-01-01

days = 8491

отрегулировано2 = 1946-10-03

0 голосов
/ 08 октября 2019

Если у вас есть метод generateRandomDate() и вы хотите очистить список дат, вам нужно выполнить следующее:

final Map<LocalDate, LocalDate> map = new HashMap<>();

List<LocalDate> initialDates = ...;
List<LocalDate> scrubbedDates =
    initialCalendars.stream()
                    .map(date -> map.computeIfAbsent(date, __ -> generateRandomDate()))
                    .collect(toList());

Те же даты будут удалены с теми же случайно сгенерированными.


Метод generateRandomDate может быть реализован следующим образом:

public static LocalDate generateRandomDate() {
    Random random = new Random();
    int minDay = (int) LocalDate.of(1900, 1, 1).toEpochDay();
    int maxDay = (int) LocalDate.of(2015, 1, 1).toEpochDay();
    long randomDay = minDay + random.nextInt(maxDay - minDay);

    return LocalDate.ofEpochDay(randomDay);
}

Отрезанный код генерации даты заимствован из здесь .

0 голосов
/ 08 октября 2019

Класс Random может принимать начальное число, это должно сработать:

public static int randBetween (int start, int end){
    int seed = end +(start*10000);
    return start + new Random(seed).nextInt((end-start));
}

Суть в том, что: использование end +(start*10000) должно дать уникальное, но надежное начальное число.

...