Skip to content

Instantly share code, notes, and snippets.

@pyllyukko
Created September 30, 2015 12:31
Show Gist options
  • Save pyllyukko/f5dbf67ab6f771471b5b to your computer and use it in GitHub Desktop.
Save pyllyukko/f5dbf67ab6f771471b5b to your computer and use it in GitHub Desktop.
Finnish personal identity code calculator/generator
#!/bin/bash
################################################################################
# hetu.sh - finnish personal identity code calculator/generator
#
# by pyllyukko - https://github.com/pyllyukko
#
# more info:
# https://secure.wikimedia.org/wikipedia/en/wiki/National_identification_number#Finland
#
################################################################################
#[ ${BASH_VERSINFO[0]} -eq 4 ] && shopt -s compat31
shopt -s nocasematch
declare -r MATRIX="0123456789ABCDEFHJKLMNPRSTUVWXY"
declare -ar SEX=("woman" "man")
declare -a DAYS=(31 28 31 30 31 30 31 31 30 31 30 31)
################################################################################
function usage() {
cat 0<<-EOF
usage: ${0##*/} DDMMYYCZZZ||YYYY||DDMMYY
examples:
${0##*/} 1980
${0##*/} 010101-001
${0##*/} 010101
EOF
return 0
} # usage()
################################################################################
function calculate() {
local DDMMYYCZZZ
local ZZZ
local DAY
local MONTH
if [ ${#} -ne 1 -o ${#1} -ne 10 ] || \
[[ ! ${1} =~ ^[0-3][0-9][01][0-9]{3}[-+a][0-9]{3}$ ]] || \
[ ${1:2:2} -gt 12 -o ${1:2:2} -lt 1 ]
then
echo "${FUNCNAME}(): error!" 1>&2
return 1
fi
DDMMYYCZZZ="${1}"
ZZZ="${DDMMYYCZZZ:7:3}"
DAY=`expr "${DDMMYYCZZZ:0:2}" : '^0\?\([0-9]\+\)$'`
MONTH=`expr "${DDMMYYCZZZ:2:2}" : '^0\?\([0-9]\+\)$'`
#echo "${FUNCNAME}(): DEBUG: DAY=\"${DAY}\""
set -- ${1/[-Aa+]/}
# here be bug!
[ ${DAY} -gt ${DAYS[$[${MONTH}-1]]-0} -o ${DAY} -lt 1 ] && {
return 3
}
echo "${DDMMYYCZZZ}${MATRIX:$[${1#0}%${#MATRIX}]:1} ${SEX[$[${ZZZ:2:1}%2]]}"
return 0
} # calculate()
################################################################################
function generate() {
# $1 = year
# this function still needs to be finished...
local DAY
local MONTH
for MONTH in {1..12}
do
for DAY in {1..31}
do
[ ${DAY#0} -gt ${DAYS[ $[ ${MONTH#0} - 1 ] ]} ] && continue
# according to cia world factbook (9.9.2010):
# population = 5,250,275 (July 2010 est.)
# birth rate = 10.38 births/1,000 population (2010 est.)
# ...that's roughly 149 per day. of course that's not the whole truth,
# but we'll go with that for now.
# personal identification number
for PIN in {1..149}
do
[ ${#PIN} -eq 1 ] && PIN="00${PIN}"
[ ${#PIN} -eq 2 ] && PIN="0${PIN}"
[ ${#DAY} -eq 1 ] && DAY="0${DAY}"
[ ${#MONTH} -eq 1 ] && MONTH="0${MONTH}"
calculate "${DAY}${MONTH}${1:2:2}${C}${PIN}"
done
done
done
return 0
} # generate()
################################################################################
function check_leap_year() {
if [[ ! ${YY} =~ ^[0-9]{2}$ || ! ${CENTURY} =~ ^[0-9]{4}$ ]]
then
echo "${FUNCNAME}(): error!"
return 1
fi
[ $[(${YY#0}+${CENTURY})%4] -eq 0 -a \
$[(${YY#0}+${CENTURY})%100] -ne 0 -o \
$[(${YY#0}+${CENTURY})%400] -eq 0 \
] && {
#echo "${FUNCNAME}(): DEBUG: $((${CENTURY}+${YY#0})) is a leap year"
DAYS[1]=29
}
return 0
} # check_leap_year()
################################################################################
if [ ${#1} -eq 4 ]
then
case "${1:0:2}" in
"18") C="+" ;;
"19") C="-" ;;
"20") C="A" ;;
*)
echo "invalid century!" 1>&2
exit 1
;;
esac
CENTURY=$((${1:0:2}*100))
YY="${1:2:2}"
check_leap_year
generate "${1}"
elif [ ${#1} -eq 10 ]
then
YY="${1:4:2}"
C="${1:6:1}"
case "${C}" in
"a") CENTURY=2000 ;;
"+") CENTURY=1800 ;;
"-") CENTURY=1900 ;;
*)
echo "invalid input!" 1>&2
exit 1
;;
esac
check_leap_year
calculate "${1}"
elif [ ${#1} -eq 6 ]
then
# TODO: 002-899
for I in {100..300}
do
#if [ $(( I % 2 )) = 1 ] # woman only
if [ $(( I % 2 )) = 0 ] # man only
then
continue
fi
calculate "${1}-${I}"
done
else
usage
exit 1
fi
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment