Created
September 30, 2015 12:31
-
-
Save pyllyukko/f5dbf67ab6f771471b5b to your computer and use it in GitHub Desktop.
Finnish personal identity code calculator/generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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