Analisando datas de linguagem natural arbitrárias sob BSD

3

Estou usando o comando data do GNU para analisar datas de linguagem natural arbitrárias - por exemplo, para detectar se um determinado registro de data e hora da última semana, eu posso fazer:

if [ "$timestamp" -lt "$(date +"%s" -d "last sunday")" ]; then ...

Agora, quando estou tentando migrar meu script para o FreeBSD, como obtenho a mesma funcionalidade? man date não mostrou nenhuma promessa, a menos que eu tenha perdido algo óbvio.

    
por Guss 05.08.2014 / 17:08

3 respostas

5

Existem vários comandos no FreeBSD que usam a mesma API do GNU date para inserir datas de idioma natural do usuário . Acabei de encontrar um que pode ser enganado para converter essa data em tempo de Unix:

/usr/sbin/fifolog_reader -B 'last sunday' /dev/null 2>&1 |
  sed 's/^From[[:blank:]]*\([0-9]*\).*//p'

(note que pelo menos no FreeBSD 9.1-RELEASE-p2 onde eu experimentei isso, ele parece funcionar de maneira confiável se você estiver em um fuso horário UTC e as especificações de data que ele reconhece não são necessariamente as mesmas reconhecidas por Data GNU).

Note que alguns shells têm essa capacidade incorporada.

ksh93 :

if (( timestamp < $(printf '%(%s)T' 'last sunday') )); then

zsh :

autoload calendar_scandate
calendar_scandate 'last sun'
if (( timestamp < REPLY)); then...

Ou você pode usar perl e Date::Manip se instalado:

last_sun=$(perl -MDate::Manip -e 'print UnixDate("last sunday","%s")')
if [ "$timestamp" -lt "$last_sun" ]; then...

Ou:

if perl -MDate::Manip -e 'exit 1 unless $ARGV[0] < UnixDate("last sunday","%s")
    ' "$timestamp"; then....

Se o objetivo for verificar os registros de data e hora do arquivo, observe que o FreeBSD find suporta:

find file -prune -newermt 'last sunday'

Neste caso, se você quiser a hora do início desta semana (semanas começando no domingo), você pode fazer:

week_start=$(($(date '+%s - 86400*%w - 3600*%H - 60*%M - %S')))

Isso deve funcionar tanto no GNU quanto no FreeBSD (ou qualquer sistema em que %s seja suportado).

Em fusos horários com horário de verão, isso será desligado por uma hora em torno da mudança de / para o horário de verão.

    
por 05.08.2014 / 17:39
2

Provavelmente, a melhor maneira de garantir compatibilidade é instalar a data GNU no sistema FreeBSD.

Você pode instalar o pacote coreutils da coleção de ports do FreeBSD. Isso colocará o comando de data do GNU em /usr/local/bin/gdate .

    
por 05.08.2014 / 20:15
1

Embora possa não ser aplicável a todas as operações que podem ser expressas facilmente em linguagem natural, o date do FreeBSD possui o operador -v que permite definir valores arbitrários e relativos para separar campos de data, e isso pode ser repetido conforme necessário para produzir a maioria dos efeitos.

Por exemplo, para obter o "último domingo", pode-se aplicar "zerar todos os campos de tempo" seguido de "zero fora do dia da semana", assim:

date -v0S -v0M -v0H -v0w

então bash-speak para "dar-me os segundos desde a época do início do último domingo, independentemente de você estar rodando em Linux ou BSD", será assim:

last_sunday_start() {
    if [ "$(uname)" = "Linux" ]; then
        date +"%s" -d "next sunday -1 week"
    else
        date -v0S -v0M -v0H -v0w +"%s"
    fi
}

Observe que o exemplo de date do GNU na pergunta está incorreto se você deseja obter a "última vez que o horário de domingo 00:00:00 ocorreu" - ele retornará o início do domingo anterior quando chamado durante o domingo. O código acima também corrige a especificação de data e hora do GNU para isso.

    
por 06.08.2014 / 15:20

Tags