text:
{% extends "registration/registration_base.html" %}
{% load url from future %}
{% load i18n %}

{% block title %}{% trans "Password change successful" %}{% endblock %}

{% block masthead %}

{% trans "Password change successful" %}

{% endblock %}

{% block content %}

{% trans "Your password has been changed." %}

{% trans "Back to dashboard" %}
{% endblock %}


text:
Вопросы для интервью системного администратора Linux/DevOps
===========================================================

Коллекция вопросов для собеседования linux сисадмина/devops. Не стесняйтесь добавлять свои через pull request'ы, issues или сообщением по электронной почте.

## Содержание

  1. [Участники](#contributors)
  1. [Общие вопросы](#general)
  1. [Простые вопросы о Linux](#simple)
  1. [Вопросы среднего уровня о Linux](#medium)
  1. [Сложные вопросы о Linux](#hard)
  1. [Вопросы экспертного уровня о Linux](#expert)
  1. [Вопросы по сетям](#network)
  1. [Вопросы о MySQL](#mysql)
  1. [Вопросы о DevOps практиках](#devop)
  1. [Забавные вопросы](#fun)
  1. [Время демо](#demo)
  1. [Другие ссылки](#references)

#### [[⬆]](#toc) Участники:

* [moregeek](https://github.com/moregeek)
* [typhonius](https://github.com/typhonius)
* [schumar](https://github.com/schumar)
* [negesti](https://github.com/negesti)
* peter
* [andreashappe](https://github.com/andreashappe)
* [quatrix](https://github.com/quatrix)
* [biyanisuraj](https://github.com/biyanisuraj)
* [pedroguima](https://github.com/pedroguima)
* Ben
* [bharatnc](https://github.com/bharatnc)

#### [[⬆]](#toc) Общие вопросы:

* Что вы узнали за вчера/эту неделю?
* Расскажите о предпочитаемом окружении разработчика/администратора. (OS, редактор, браузеры, инструменты и т.п.)
* Расскажите о последнем проекте на Linux, который вы закончили.
* Расскажите о самой большой неудаче, которую вы допустили [какой-то период времени] и как вы изменились на сегодняшний день. Что вы вынесли из этого опыта?
* Почему мы должны выбрать вас?
* Какую роль играет DNS в сети?
* Что такое HTTP?
* Что такое HTTP прокси и как он работает?
* Опишите кратко как работает HTTPS?
* Что такое SMTP? Расскажите кратко сценарий доставки сообщения через SMTP.
* Что такое RAID? Что такое RAID0, RAID1, RAID5, RAID10?
* Что такое резервная копия 0-го уровня? Что такое инкрементальная резервная копия?
* Опишите иерархию файловой системы в Linux.

#### [[⬆]](#toc) Простые вопросы о Linux:

* Какое имя и UID администратора?
* Как посмотреть все файлы в каталоге, включая скрытые?
* Какая команда в Unix/Linux удаляет каталог со всем его содержимым?
* Какая команда в Unix/Linux показывает свободную/используемую память? Существует ли свободная память в Linux?
* Как найти строку "my konfu is the best" в файлах каталога рекурсивно?
* Как подключиться к удаленному серверу или что такое SSH?
* Как получить все переменные окружения и как их можно использовать?
* Я получил "command not found" при запуске ```ifconfig -a```. Что может быть не так?
* Что произойдет, если я нажму TAB-TAB?
* Какая команда показывает доступное свободное пространство на диске в Unix/Linux?
* Какие команды вы знаете, которые могут быть использованы для проверки DNS записей?
* Какая команда Unix/Linux используется для изменения владельца файла, прав доступа к файлу?
* Что делает команда ```chmod +x FILENAME```?
* Что означают права 0750 для файла?
* Что означают права 0750 для каталога?
* Как добавить пользователя без прав входа в систему?
* Как добавить/убрать пользователя в/из группы?
* Что такое bash алиас?
* Как установить email для пользователя root?
* Что делает Ctrl+c?
* Что содержится в файле /etc/services?
* Как перенаправить STDOUT и STDERR в bash?
* Какая разница между UNIX и Linux?
* В чем разница между Telnet и SSH?
* Объясните три усредненных значения load average и что они означают? Какой командой можно посмотреть load average?
* Можете назвать букву в нижнем регистре, которая не является валидной опцией для GNU ```ls```?
* Что такое модуль ядра Linux?
* Расскажите по шагам как загрузить систему в однопользовательском режиме для решения проблем.
* Расскажите по шагам как вы будете решать проблему с ошибкой 404 в веб-приложении, которое вы обслуживаете.

#### [[⬆]](#toc) Вопросы среднего уровня о Linux:

* Что делают следующие команды и как вы из будете использовать?
 * ```tee```
 * ```awk```
 * ```tr```
 * ```cut```
 * ```tac```
 * ```curl```
 * ```wget```
 * ```watch```
 * ```head```
 * ```tail```
* Что делает ```&``` в конце команды?
* Что делает ```& disown``` в конце команды?
* Что такое пакетный фильтр и как он работает?
* Что такое виртуальная память?
* Что такое swap и для чего он используется?
* Что такое A-запись, NS-запись, PTR-запись, CNAME-запись, MX-запись?
* Знаете ли вы еще какие-либо RR-записи и для чего они используются?
* Что такое Split-Horizon DNS?
* Что такое sticky bit?
* Что делает установленный на файл immutable bit?
* Какая разница между символическими и жесткими ссылками? Что произойдет если удалить символическую/жесткую ссылку?
* Что такое inode и какая информация хранится в inode?
* Как принудительно запустить проверку файловой системы при следующей перезагрузке?
* Что такое SNMP и для чего он используется?
* Что такое уровень запуска и как узнать текущий?
* Что такое SSH port forwarding?
* Какая разница между локальным и удаленным пробросом портов SSH?
* Какие шаги надо предпринять, чтоб добавить пользователя в систему не используя утилиты useradd/adduser?
* Что такое MAJOR и MINOR нумерация спец. файлов?
* Опишите команду mknod и когда она используется?
* Опишите сценарий, когда вы можете получить ошибку "filesystem is full", но 'df' показывает наличие свободного места.
* Опишите сценарий, когда вы удаляете файл,но 'df' не показывает, что место освободилось.
* Опишите как работает 'ps'.
* Что случиться, если процесс-потомок умрет и не будет процесса-родителя, ожидающего его и что в этом плохого?
* Объясните кратко каждое из состояний процесса.
* Как узнать какой процесс слушает указанный порт?
* Что такое зомби-процесс и какова его причина возникновения?
* Вы запускаете bash скрипт и хотите видеть его вывод на экране и одновременно сохранить этот вывод в файл. Как это сделать?
* Объясните, что делает echo "1" > /proc/sys/net/ipv4/ip_forward.
* Кратко объясните, какие шаги надо предпринять, чтоб создать и установить сертификат для сайта https://foo.example.com.
* Можно ли создать несколько HTTPS виртуальных хостов, используя один IP?
* Что такое wildcard сертификат?
* Какие типы файловых систем в Linux вам известны?
* В чем разница между процессом и потоком? И родительским и потомком процессами после системного вызова fork?
* В чем разница между exec и fork?
* Для чего используется ```nohup```?
* В чем разница между этими двумя командами?
 * ```myvar=hello```
 * ```export myvar=hello```
* Как много NTP севреров настроено в вашем локальном ntp.conf?
* Что означает колонка 'reach' в выводе ```ntpq-p```?
* Вам необходимо обновить ядро на 100-1000 серверах, как вы будете это делать?
* Как можно получить Host, Channel, IS, LUN для SCSI диска?
* Как можно ограничить использование памяти для процесса?
* Что такое быстрый поиск и замена в bash (^x^y)?
* Какие вы знаете альтернативные оболочки? Какую вы используете?
* Что такое tarpipe (или, как вы будете копировать все, включая жесткие ссылки и специальные файлы, с одного сервера на другой)?
* Как можно проверить, что пакет httpd уже был установлен?
* Как посмотреть содержимое установочного пакета?
* Как вы определите какой пакет лучше: openssh-server-5.3p1-118.1.el6_8.x86_64 или openssh-server-6.6p1-1.el6.x86_64?
* Как вы можете объяснить мне разницу между хранилищем, основанным на блоках и объектах?

#### [[⬆]](#toc) Сложные вопросы о Linux:

* Что такое туннель и как вы можете обойти http прокси?
* В чем разница между IDS и IPS?
* Какие горячие клавиши вы используете регулярно?
* Что такое Linux Standard Base?
* Что такое атомарная операция?
* Вы только что настроили http сервер, который не запустился после рестарта. Что вы будете делать?
* Какие ключи содержатся в ~/.ssh/authorized_keys и для чего нужен этот файл?
* Я добавил свой публичный ключ в authorized_keys, но до сих пор получаю запрос пароля. Что может быть не так?
* Вы когда-нибудь собирали RPM, DEB или solaris пакеты?
* Что сделает ```:(){ :|:& };:``` с вашей системой?
* Как можно перехватить Linux сигнал из скрипта?
* Можно ли перехватить SIGKILL?
* Что происходит, когда ядро Linux запускает OOM killer и как он выбирает какой процесс необходимо убить в первую очередь?
* Опишите процесс загрузки Linux с максимально возможным количеством деталей, начиная с момента включения компьютера и заканчивая получением приглашения командной строки.
* Что такое закрытие в chroot?
* При попытке отмонтировать каталог получаем ошибку занятости, как найти какой PID держит каталог?
* Что такое LD_PRELOAD и когда он используется?
* Вы запустили бинарник и ничего не произошло. Как вы будете искать проблему?
* Что такое cgroups? Можете ли вы указать сценарий, когда это может быть использовано?
* Как можно удалить файл, имя которого содержит непечатные символы?
* Как можно увеличить/уменьшить приоритет процесса в Linux?
* Что такое run-levels в Linux?

#### [[⬆]](#toc) Вопросы экспертного уровня о Linux:

* Запущенный процесс получает ```EAGAIN: Resource temporarily unavailable``` при чтении сокета. Как можно закрыть этот плохой сокет/файловый дескриптор без убивания процесса?

#### [[⬆]](#toc) Вопросы по сетям:

* Что такое localhost и почему ```ping localhost``` может не работать?
* В чем сходство между "ping" и "traceroute"? Как traceroute находит промежуточные хосты?
* Какая команда можно использовать для поиска всех открытых портов и/или соединений с сокетами на машине?
* Валидный ли IP адрес 300.168.0.123?
* Какие IP диапазоны/подсети являются частными или не маршрутизируемыми (RFC 1918)?
* Что такое VLAN?
* Что такое ARP и для чего используется?
* В чем разница между TCP и UDP?
* Какова цель шлюза по умолчанию?
* Какая команда используется для просмотра таблицы маршрутизации в Linux?
* TCP-соединение в сети может быть однозначно определено четырьмя вещами. Что это за вещи?
* Когда клиент использует бразер для подключения к веб-серверу, какие порты источника и назначения будут у этого соединения?
* Как можно добавить IPv6 адрес для конкретного интерфейса?
* Вы добавили IPv4 и IPv6 адреса на eth0 интерфейс. Ping на v4 адрес работает, но ping на v6 адрес дает ответ ```sendmsg: operation not permitted```. Что может быть не так?
* Что такое SNAT и когда он должен быть использован?
* Объясните, как можно войти по ssh на Linux сервер, который сбрасывает (DROP) все новые входящие пакеты, используя SSH туннель.
* Как вы будете противодействовать DDoS атаке?
* Как можно посмотреть содержимое ip пакета?
* Что такое IPoAC (RFC 1149)?

#### [[⬆]](#toc) Вопрос о MySQL:

* Как создать пользователя?
* Как предоставить права пользователю?
* В чем разница между 'left' и 'right' join?
* Объясните кратко разницу между InnoDB и MyISAM.
* Зачем надо запускать "mysql_secure_installation" после установки MySQL?
* Как проверить какие задачи запущены?
* Как вы делаете бекап MySQL?

#### [[⬆]](#toc) Вопросы о DevOps:

* Как вы можете описать ваш workflow при создании скрипта?
* Что такое GIT?
* Что такое динамически/статически слинкованные файлы?
* Что делает "./configure && make && make install"?
* Для чего используется puppet/chef/ansible?
* Для чего используется Nagios/Zenoss/NewRelic?
* Для чего используется Jenkins/TeamCity/GoCI?
* В чем разница между контейнеризацией и виртуализацией?
* Как создать нового postgres пользователя?
* Что такое виртуальный IP адрес? Что такое кластер?
* Как вывести все строки печатных символов, присутствующих в файле?
* Как найти зависимости для библиотеки?
* Что такое Automake и Autoconf?
* ./configure вывела ошибку, что libfoobar не найдена в система, как вы будете исправлять это? Что может быть не так?
* Какие преимущества/недостатки у скриптов против компилируемых программ?
* Какая связь между непрерывной доставкой (continuous delivery) и DevOps?
* Каковы важные аспекты системы непрерывной интеграции и развертывания?
* Как бы вы включили совместное использование сетевых файлов в AWS, которые позволили бы экземплярам EC2 в нескольких зонах доступности обмениваться данными?

#### [[⬆]](#toc) Забавные вопросы::

* Небрежный сисадмин запустил команду ```chmod 444 /bin/chmod``` - как ву будете исправлять проблему?
* Я потерял пароль пользователя root. Что мне делать?
* Я перезагрузил удаленный сервер, но спустя 10 минут все еще не могу зайти по SSH. Что может быть не так?
* Если бы вы попали на пустынный остров с 5 утилитами коммандной строки, то какие утилиты это были бы?
* Вы сталкиваетесь с случайным компьютером и, похоже, это консоль к мирозданию. Что первое вы наберете?
* Расскажите о креативном использовании ssh в вашей практике?
* Вы случайно удалили запущенный скрипт, как вы будете его восстанавливать?
* Что случится 19 января 2038 года?
* Как перезагрузить сервер когда команда reboot не доступна?

#### [[⬆]](#toc) Время демо:

* Распакуйте test.tar.gz без использования man и google.
* Удалите все "*.pyc" файлы рекурсивно из testdir.
* Найдите все "my konfu is the best" во всех *.py файлах.
* Замените все вхождения "my konfu is the best" на "I'm a linux jedi master" во всех *.txt файлах.
* Проверьте доступность 443 порта на машине с IP X.X.X.X.
* Получите страницу http://myinternal.webserver.local/test.html при помощи telnet.
* Как отправить email без почтового клиента, только с помощью командной строки?
* Напишите метод ```get_prim``` в python/perl/bash/pseudo.
* Найдите все файлы, доступ к которым был осуществлен за последние 30 дней.
* Объясните следующую команду ```(date ; ps -ef | awk '{print $1}' | sort | uniq | wc -l ) >> Activity.log```
* Напишите скрипт, показывающий разницу двух каталогов.
* Из лог файла, содержащего ```<TIME> : [MESSAGE] : [ERROR_NO] - Human readable text``` выведите сумму/количество указанной ошибки, которая повторяется каждый час, или указанный час.

#### [[⬆]](#toc) Другие ссылки:

Некоторые вопросы 'заимствованы' из других замечательных ссылок, например:

* https://github.com/darcyclarke/Front-end-Developer-Interview-Questions
* https://github.com/kylejohnson/linux-sysadmin-interview-questions/blob/master/test.md
* http://slideshare.net/kavyasri790693/linux-admin-interview-questions

mime_type: text/plain


text:
Linux System Administrator/DevOps Interview Questions
====================================================

A collection of linux sysadmin/devops interview questions. Feel free to contribute via pull requests, issues or email messages.

## Table of Contents

  1. [Contributors](#contributors)
  1. [General Questions](#general)
  1. [Simple Linux Questions](#simple)
  1. [Medium Linux Questions](#medium)
  1. [Hard Linux Questions](#hard)
  1. [Expert Linux Questions](#expert)
  1. [Networking Questions](#network)
  1. [MySQL Questions](#mysql)
  1. [DevOps Questions](#devop)
  1. [Fun Questions](#fun)
  1. [Demo Time](#demo)
  1. [Other Great References](#references)

#### [[⬆]](#toc) Contributors:

* [moregeek](https://github.com/moregeek)
* [typhonius](https://github.com/typhonius)
* [schumar](https://github.com/schumar)
* [negesti](https://github.com/negesti)
* peter
* [andreashappe](https://github.com/andreashappe)
* [quatrix](https://github.com/quatrix)
* [biyanisuraj](https://github.com/biyanisuraj)
* [pedroguima](https://github.com/pedroguima)
* Ben
* [bharatnc](https://github.com/bharatnc)

#### [[⬆]](#toc) General Questions:

* What did you learn yesterday/this week?
* Talk about your preferred development/administration environment. (OS, Editor, Browsers, Tools etc.)
* Tell me about the last major Linux project you finished.
* Tell me about the biggest mistake you've made in [some recent time period] and how you would do it differently today. What did you learn from this experience?
* Why we must choose you?
* What function does DNS play on a network?
* What is HTTP?
* What is an HTTP proxy and how does it work?
* Describe briefly how HTTPS works.
* What is SMTP? Give the basic scenario of how a mail message is delivered via SMTP.
* What is RAID? What is RAID0, RAID1, RAID5, RAID10?
* What is a level 0 backup? What is an incremental backup?
* Describe the general file system hierarchy of a Linux system.
* Which difference have between public and private SSH key?

#### [[⬆]](#toc) Simple Linux Questions:

* What is the name and the UID of the administrator user?
* How to list all files, including hidden ones, in a directory?
* What is the Unix/Linux command to remove a directory and its contents?
* Which command will show you free/used memory? Does free memory exist on Linux?
* How to search for the string "my konfu is the best" in files of a directory recursively?
* How to connect to a remote server or what is SSH?
* How to get all environment variables and how can you use them?
* I get "command not found" when I run ```ifconfig -a```. What can be wrong?
* What happens if I type TAB-TAB?
* What command will show the available disk space on the Unix/Linux system?
* What commands do you know that can be used to check DNS records?
* What Unix/Linux commands will alter a files ownership, files permissions?
* What does ```chmod +x FILENAME``` do?
* What does the permission 0750 on a file mean?
* What does the permission 0750 on a directory mean?
* How to add a new system user without login permissions?
* How to add/remove a group from a user?
* What is a bash alias?
* How do you set the mail address of the root/a user?
* What does CTRL-c do?
* What does CTRL-d do?
* What does CTRL-z do?
* What is in /etc/services?
* How to redirect STDOUT and STDERR in bash? (> /dev/null 2>&1)
* What is the difference between UNIX and Linux.
* What is the difference between Telnet and SSH?
* Explain the three load averages and what do they indicate. What command can be used to view the load averages?
* Can you name a lower-case letter that is not a valid option for GNU ```ls```?
* What is a Linux kernel module?
* Walk me through the steps in booting into single user mode to troubleshoot a problem.
* Walk me through the steps you'd take to troubleshoot a 404 error on a web application you administer.
* What is ICMP protocol? Why do you need to use?

#### [[⬆]](#toc) Medium Linux Questions:

* What do the following commands do and how would you use them?
 * ```tee```
 * ```awk```
 * ```tr```
 * ```cut```
 * ```tac```
 * ```curl```
 * ```wget```
 * ```watch```
 * ```head```
 * ```tail```
 * ```less```
 * ```cat```
 * ```touch```
 * ```sar```
 * ```netstat```
 * ```tcpdump```
 * ```lsof```
* What does an ```&``` after a command do?
* What does ```& disown``` after a command do?
* What is a packet filter and how does it work?
* What is Virtual Memory?
* What is swap and what is it used for?
* What is an A record, an NS record, a PTR record, a CNAME record, an MX record?
* Are there any other RRs and what are they used for?
* What is a Split-Horizon DNS?
* What is the sticky bit?
* What does the immutable bit do to a file?
* What is the difference between hardlinks and symlinks? What happens when you remove the source to a symlink/hardlink?
* What is an inode and what fields are stored in an inode?
* How to force/trigger a file system check on next reboot?
* What is SNMP and what is it used for?
* What is a runlevel and how to get the current runlevel?
* What is SSH port forwarding?
* What is the difference between local and remote port forwarding?
* What are the steps to add a user to a system without using useradd/adduser?
* What is MAJOR and MINOR numbers of special files?
* Describe the mknod command and when you'd use it.
* Describe a scenario when you get a "filesystem is full" error, but 'df' shows there is free space.
* Describe a scenario when deleting a file, but 'df' not showing the space being freed.
* Describe how 'ps' works.
* What happens to a child process that dies and has no parent process to wait for it and what’s bad about this?
* Explain briefly each one of the process states.
* How to know which process listens on a specific port?
* What is a zombie process and what could be the cause of it?
* You run a bash script and you want to see its output on your terminal and save it to a file at the same time. How could you do it?
* Explain what echo "1" > /proc/sys/net/ipv4/ip_forward does.
* Describe briefly the steps you need to take in order to create and install a valid certificate for the site https://foo.example.com.
* Can you have several HTTPS virtual hosts sharing the same IP?
* What is a wildcard certificate?
* Which Linux file types do you know?
* What is the difference between a process and a thread? And parent and child processes after a fork system call?
* What is the difference between exec and fork?
* What is "nohup" used for?
* What is the difference between these two commands?
 * ```myvar=hello```
 * ```export myvar=hello```
* How many NTP servers would you configure in your local ntp.conf?
* What does the column 'reach' mean in ```ntpq -p``` output?
* You need to upgrade kernel at 100-1000 servers, how you would do this?
* How can you get Host, Channel, ID, LUN of SCSI disk?
* How can you limit process memory usage?
* What is bash quick substitution/caret replace(^x^y)?
* Do you know of any alternative shells? If so, have you used any?
* What is a tarpipe (or, how would you go about copying everything, including hardlinks and special files, from one server to another)?
* How can you tell if the httpd package was already installed?
* How can you list the contents of a package?
* How can you determine which package is better: openssh-server-5.3p1-118.1.el6_8.x86_64 or openssh-server-6.6p1-1.el6.x86_64 ?
* Can you explain to me the difference between block based, and object based storage?

#### [[⬆]](#toc) Hard Linux Questions:

* What is a tunnel and how you can bypass a http proxy?
* What is the difference between IDS and IPS?
* What shortcuts do you use on a regular basis?
* What is the Linux Standard Base?
* What is an atomic operation?
* Your freshly configured http server is not running after a restart, what can you do?
* What kind of keys are in ~/.ssh/authorized_keys and what it is this file used for?
* I've added my public ssh key into authorized_keys but I'm still getting a password prompt, what can be wrong?
* Did you ever create RPM's, DEB's or solaris pkg's?
* What does ```:(){ :|:& };:``` do on your system?
* How do you catch a Linux signal on a script?
* Can you catch a SIGKILL?
* What's happening when the Linux kernel is starting the OOM killer and how does it choose which process to kill first?
* Describe the linux boot process with as much detail as possible, starting from when the system is powered on and ending when you get a prompt.
* What's a chroot jail?
* When trying to umount a directory it says it's busy, how to find out which PID holds the directory?
* What's LD_PRELOAD and when it's used?
* You ran a binary and nothing happened. How would you debug this?
* What are cgroups? Can you specify a scenario where you could use them?
* How can you remove/delete a file with file-name consisting of only non-printable/non-type-able characters?
* How can you increase or decrease the priority of a process in Linux?

#### [[⬆]](#toc) Expert Linux Questions:

* A running process gets ```EAGAIN: Resource temporarily unavailable``` on reading a socket. How can you close this bad socket/file descriptor without killing the process?
* What do you control with swapiness?
* How do you change TCP stack buffers? How do you calculate it?
* What is Huge Tables? Why isn't it enabled by default? Why and when use it?
* What is LUKS? How to use it?

#### [[⬆]](#toc) Networking Questions:

* What is localhost and why would ```ping localhost``` fail?
* What is the similarity between "ping" & "traceroute" ? How is traceroute able to find the hops.
* What is the command used to show all open ports and/or socket connections on a machine?
* Is 300.168.0.123 a valid IPv4 address?
* Which IP ranges/subnets are "private" or "non-routable" (RFC 1918)?
* What is a VLAN?
* What is ARP and what is it used for?
* What is the difference between TCP and UDP?
* What is the purpose of a default gateway?
* What is command used to show the routing table on a Linux box?
* A TCP connection on a network can be uniquely defined by 4 things. What are those things?
* When a client running a web browser connects to a web server, what is the source port and what is the destination port of the connection?
* How do you add an IPv6 address to a specific interface?
* You have added an IPv4 and IPv6 address to interface eth0. A ping to the v4 address is working but a ping to the v6 address gives you the response ```sendmsg: operation not permitted```. What could be wrong?
* What is SNAT and when should it be used?
* Explain how could you ssh login into a Linux system that DROPs all new incoming packets using a SSH tunnel.
* How do you stop a DDoS attack?
* How can you see content of an ip packet?
* What is IPoAC (RFC 1149)?
* What will happen when you bind port 0?

#### [[⬆]](#toc) MySQL questions:

* How do you create a user?
* How do you provide privileges to a user?
* What is the difference between a "left" and a "right" join?
* Explain briefly the differences between InnoDB and MyISAM.
* Describe briefly the steps you need to follow in order to create a simple master/slave cluster.
* Why should you run "mysql_secure_installation" after installing MySQL?
* How do you check which jobs are running?
* How would you take a backup of a MySQL database?

#### [[⬆]](#toc) DevOps Questions:

* Can you describe your workflow when you create a script?
* What is GIT?
* What is a dynamically/statically linked file?
* What does "./configure && make && make install" do?
* What is puppet/chef/ansible used for?
* What is Nagios/Zenoss/NewRelic used for?
* What is Jenkins/TeamCity/GoCI used for?
* What is the difference between Containers and VMs?
* How do you create a new postgres user?
* What is a virtual IP address? What is a cluster?
* How do you print all strings of printable characters present in a file?
* How do you find shared library dependencies?
* What is Automake and Autoconf?
* ./configure shows an error that libfoobar is missing on your system, how could you fix this, what could be wrong?
* What are the advantages/disadvantages of script vs compiled program?
* What's the relationship between continuous delivery and DevOps?
* What are the important aspects of a system of continuous integration and deployment?
* How would you enable network file sharing within AWS that would allow EC2 instances in multiple availability zones to share data?

#### [[⬆]](#toc) Fun Questions:

* A careless sysadmin executes the following command: ```chmod 444 /bin/chmod ``` - what do you do to fix this?
* I've lost my root password, what can I do?
* I've rebooted a remote server but after 10 minutes I'm still not able to ssh into it, what can be wrong?
* If you were stuck on a desert island with only 5 command-line utilities, which would you choose?
* You come across a random computer and it appears to be a command console for the universe. What is the first thing you type?
* Tell me about a creative way that you've used SSH?
* You have deleted by error a running script, what could you do to restore it?
* What will happen on 19 January 2038?
* How to reboot server when reboot command is not responding?

#### [[⬆]](#toc) Demo Time:

* Unpack test.tar.gz without man pages or google.
* Remove all "*.pyc" files from testdir recursively?
* Search for "my konfu is the best" in all *.py files.
* Replace the occurrence of "my konfu is the best" with "I'm a linux jedi master" in all *.txt files.
* Test if port 443 on a machine with IP address X.X.X.X is reachable.
* Get http://myinternal.webserver.local/test.html via telnet.
* How to send an email without a mail client, just on the command line?
* Write a ```get_prim``` method in python/perl/bash/pseudo.
* Find all files which have been accessed within the last 30 days.
* Explain the following command ```(date ; ps -ef | awk '{print $1}' | sort | uniq | wc -l ) >> Activity.log```
* Write a script to list all the differences between two directories.
* In a log file with contents as ```<TIME> : [MESSAGE] : [ERROR_NO] - Human readable text``` display summary/count of specific error numbers that occurred every hour or a specific hour.

#### [[⬆]](#toc) Other Great References:

Some questions are 'borrowed' from other great references like:

* https://github.com/darcyclarke/Front-end-Developer-Interview-Questions
* https://github.com/kylejohnson/linux-sysadmin-interview-questions/blob/master/test.md
* http://slideshare.net/kavyasri790693/linux-admin-interview-questions


text:
package dateparse

import (
	"fmt"
	"regexp"
	"strings"
	"time"
)

var (
	timePrefix = `(с|в|к|by|at)`
	timeSuffix = `(утра|вечера|мин[у]?[т]?|a[.]?m|p[.]?m)`
)

var (
	hhmmRegex                = regexp.MustCompile(fmt.Sprintf(`%s?[" "]?%s[.:]%s`, timePrefix, hourHH, minuteMM))
	hhRegex                  = regexp.MustCompile(fmt.Sprintf(`%s[" "]%s\s?%s?`, timePrefix, hourHH, timeSuffix))
	baseTimeOrientationRegex = regexp.MustCompile(fmt.Sprintf(`%s?%s?[" "]?%s`, timePrefix, datePrefix, durationSuffix))
)

func parseTime(s string, opts Opts) (t time.Time, st string) {
	switch {
	case hhmmRegex.MatchString(s):
		return calculateTime(hhmmRegex.FindStringSubmatch(s), opts)
	case hhRegex.MatchString(s):
		return calculateTime(hhRegex.FindStringSubmatch(s), opts)
	case baseTimeOrientationRegex.MatchString(s):
		return calculateTime(baseTimeOrientationRegex.FindStringSubmatch(s), opts)
	}
	return opts.Now, st
}

func calculateTime(t []string, opts Opts) (time.Time, string) {
	m := normalizeStrings(t[1:])
	switch len(m) {
	case 4:
		hour := forceInt(m[2])
		minute := forceInt(m[3])
		return getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day(), hour, minute, 0, opts), t[0]
	case 3:
		hour := forceInt(m[1])
		switch {
		case strings.Contains(morning, m[2]):
			if hour > 12 {
				hour -= 12
			}
			return getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day(), hour, 0, 0, opts), t[0]
		case strings.Contains(evening, m[2]):
			if hour < 12 {
				hour += 12
			}
			return getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day(), hour, 0, 0, opts), t[0]
		}
		minute := forceInt(m[2])
		return getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day(), hour, minute, 0, opts), t[0]
	case 2:
		switch {
		case strings.Contains(morning, m[1]):
			return getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day(), 10, 0, 0, opts), t[0]
		case strings.Contains(noon, m[1]):
			return getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day(), 12, 0, 0, opts), t[0]
		case strings.Contains(timePrefix, m[0]):
			return getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day(), forceInt(m[1]), 0, 0, opts), t[0]
		}
		return getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day(), forceInt(m[0]), forceInt(m[1]), 0, opts), t[0]
	case 1:
		switch {
		case strings.Contains(morning, m[0]):
			return getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day(), 10, 0, 0, opts), t[0]
		case strings.Contains(evening, m[0]):
			return getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day(), 18, 0, 0, opts), t[0]
		case strings.Contains(noon, m[0]):
			return getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day(), 12, 0, 0, opts), t[0]
		case strings.Contains(midnight, m[0]):
			return getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day(), 0, 0, 0, opts), t[0]

		}
	}
	return opts.Now, t[0]
}

repo_name: tada-team/dateparse

repo_language: Go


text:
package dateparse

var (
	dayDD    = `(30|31|0[1-9]|[1-2]\d|[1-9])`
	monthMM  = `(1[012]|0[1-9])`
	yearYY   = `(\d\d)`
	yearYYYY = `(20\d\dк?г?)`
	hourHH   = `(0[0-9]|1[0-9]|2[0-3]|[0-9])`
	minuteMM = `(0[0-9]|[0-5][0-9])`
)

var (
	morning  = `утром|утро|утра|morning|a.m`
	evening  = `вечером|вечер|вечера|evening|p.m`
	midnight = "полночь|ночью|midnight"
	noon     = "днем|полдень|noon|midday"
)

var (
	today              = `сегодня|today`
	tomorrow           = `завтра|tomorrow`
	afterTomorrow      = `послезавтра|after tomorrow|aftertomorrow`
	afterAfterTomorrow = `послепослезавтра|after after tomorrow|afteraftertomorrow`
	yesterday          = `вчера|yesterday`
)


text:
package dateparse

import (
	"fmt"
	"regexp"
	"strings"
	"time"
)

var (
	datePrefix = `(в|во|in|on|ровно|the|at)`
	dateSuffix = `(-ого|-го|-ва|-его|th|числа|date|\\|/|года|years|[.])`
	daySuffix  = `(-ого|-го|-ва|-его|th|числа|date|\\)`
)

var (
	baseDurRegex            = regexp.MustCompile(fmt.Sprintf(`(%s)[" "/]`, duration))
	baseDurOnlyRegex        = regexp.MustCompile(fmt.Sprintf(`(%s)$`, duration))
	baseDurTimeRegex        = regexp.MustCompile(fmt.Sprintf(`(\d\d?\d?)[" "](%s)`, durationTime))
	baseWeekOnlyRegex       = regexp.MustCompile(fmt.Sprintf(`^(%s|%s)$`, weeks, shortWeeks))
	baseWeekPrefixOnlyRegex = regexp.MustCompile(fmt.Sprintf(`^%s[" "](%s|%s)$`, datePrefix, weeks, shortWeeks))
	baseWeekPrefixRegex     = regexp.MustCompile(fmt.Sprintf(`^%s[" "](%s|%s)[" "]`, datePrefix, weeks, shortWeeks))
	baseWeekRegex           = regexp.MustCompile(fmt.Sprintf(`^(%s|%s)[" "]`, weeks, shortWeeks))
	weekDurSuffixRegex      = regexp.MustCompile(fmt.Sprintf(`%s[" "](%s)[" "]%s`, datePrefix, weeks, durationSuffix))
	durSuffixWeekRegex      = regexp.MustCompile(fmt.Sprintf(`%s?[" "]?%s[" "]%s[" "](%s)`, datePrefix, durationSuffix, datePrefix, weeks))
	durPrefixWeekRegex      = regexp.MustCompile(fmt.Sprintf(`%s[" "]%s[" "](%s)[" "]?%s?`, datePrefix, durPrefix, weeks, durationSuffix))
)

var (
	ddRegex          = regexp.MustCompile(fmt.Sprintf(`%s?[" "]?%s[" "]?%s`, datePrefix, dayDD, daySuffix))
	ddmmRegex        = regexp.MustCompile(fmt.Sprintf(`%s?[" "]?%s[/.]%s\s?%s?`, datePrefix, dayDD, monthMM, dateSuffix))
	ddMonthRegex     = regexp.MustCompile(fmt.Sprintf(`%s%s?[" "](%s)`, dayDD, dateSuffix, months))
	ddmmyyyyRegex    = regexp.MustCompile(fmt.Sprintf(`%s?[" "]?%s[/.]%s[/.]%s\s?%s?`, datePrefix, dayDD, monthMM, yearYYYY, dateSuffix))
	ddMonthyyyyRegex = regexp.MustCompile(fmt.Sprintf(`%s?[" "]?%s[" "/.](%s)[" "/.]%s\s?%s?`, datePrefix, dayDD, months, yearYYYY, dateSuffix))
	ddmmyyRegex      = regexp.MustCompile(fmt.Sprintf(`%s?[" "]?%s[/.]%s[/.]%s\s?%s?`, datePrefix, dayDD, monthMM, yearYY, dateSuffix))
	ddMonthyyRegex   = regexp.MustCompile(fmt.Sprintf(`%s?[" "]?%s[" "/.](%s)[" "/.]%s\s?%s`, datePrefix, dayDD, months, yearYY, dateSuffix))
	isoyyyymmddRegex = regexp.MustCompile(fmt.Sprintf(`%s?[" "]?%s[/.-]?%s[/.-]?%s\s?`, datePrefix, yearYYYY, monthMM, dayDD))
	isoyymmddRegex   = regexp.MustCompile(fmt.Sprintf(`%s?[" "]?%s[/.-]?%s[/.-]?%s`, datePrefix, yearYY, monthMM, dayDD))
)

var (
	durTimeRegex   = regexp.MustCompile(fmt.Sprintf(`%s?[" "]?%s[" "](\d\d?\d?)[" "]?(%s)?`, datePrefix, durPrefix, durationTime))
	durRegex       = regexp.MustCompile(fmt.Sprintf(`%s?[" "]?%s[" "](%s)?\s?(%s)`, datePrefix, durPrefix, wordNumbers, durationWds))
	wdsRegex       = regexp.MustCompile(fmt.Sprintf(`(%s)\b[" "/]?%s?`, durationWds, durationSuffix))
	wdsSuffuxRegex = regexp.MustCompile(fmt.Sprintf(`(%s)[" "/]%s[" "]%s`, durationWds, datePrefix, durationSuffix))
	wdsTimeRegex   = regexp.MustCompile(fmt.Sprintf(`%s[" "](\d\d)[" "](%s)`, datePrefix, hours))
)

var (
	mmddyyyyRegex = regexp.MustCompile(fmt.Sprintf(`%s?[" "]?%s[/.]%s[/.]%s\s?%s?`, datePrefix, monthMM, dayDD, yearYYYY, dateSuffix))
	mmddyyRegex   = regexp.MustCompile(fmt.Sprintf(`%s?[" "]?%s[/.]%s[/.]%s\s?%s?`, datePrefix, monthMM, dayDD, yearYY, dateSuffix))
	mmddRegex     = regexp.MustCompile(fmt.Sprintf(`%s?[" "]?%s[/.]%s\s?%s?`, datePrefix, monthMM, dayDD, dateSuffix))
)

func parseDate(s string, opts Opts) (t time.Time, st string) {
	switch {
	case baseDurOnlyRegex.MatchString(s):
		return calculateWordsDate(baseDurOnlyRegex.FindStringSubmatch(s), opts)
	case baseWeekPrefixOnlyRegex.MatchString(s):
		return calculateWeekDuration(baseWeekPrefixOnlyRegex.FindStringSubmatch(s), opts, 2)
	case baseWeekOnlyRegex.MatchString(s):
		return calculateWeekDuration(baseWeekOnlyRegex.FindStringSubmatch(s), opts, 1)
	case wdsSuffuxRegex.MatchString(s):
		return calculateWordsDate(wdsSuffuxRegex.FindStringSubmatch(s), opts)
	case baseDurRegex.MatchString(s):
		return calculateWordsDate(baseDurRegex.FindStringSubmatch(s), opts)
	case weekDurSuffixRegex.MatchString(s):
		return calculateWeekDuration(weekDurSuffixRegex.FindStringSubmatch(s), opts, 2)
	case baseWeekPrefixRegex.MatchString(s):
		return calculateWeekDuration(baseWeekPrefixRegex.FindStringSubmatch(s), opts, 2)
	case baseWeekRegex.MatchString(s):
		return calculateWeekDuration(baseWeekRegex.FindStringSubmatch(s), opts, 1)
	case durTimeRegex.MatchString(s):
		return calculateDuration(durTimeRegex.FindStringSubmatch(s), opts, 2)
	case durRegex.MatchString(s):
		return calculateDuration(durRegex.FindStringSubmatch(s), opts, 2)
	case durPrefixWeekRegex.MatchString(s):
		return calculateWeekDuration(durPrefixWeekRegex.FindStringSubmatch(s), opts, 3)
	case durSuffixWeekRegex.MatchString(s):
		return calculateWeekDuration(durSuffixWeekRegex.FindStringSubmatch(s), opts, -3)
	//case rareyyyymmdd.MatchString(s):
	//	return calculateFullDate(rareyyyymmdd.FindStringSubmatch(s), opts, 2, 3, 4)
	//case rareyymmdd.MatchString(s):
	//	return calculateFullDate(rareyymmdd.FindStringSubmatch(s), opts, 2, 3, 4)
	case ddMonthyyyyRegex.MatchString(s):
		return calculateFullDate(ddMonthyyyyRegex.FindStringSubmatch(s), opts, 4, 3, 2)
	case ddMonthyyRegex.MatchString(s):
		return calculateFullDate(ddMonthyyRegex.FindStringSubmatch(s), opts, 4, 3, 2)
	case ddmmyyyyRegex.MatchString(s):
		return calculateFullDate(ddmmyyyyRegex.FindStringSubmatch(s), opts, 4, 3, 2)
	case mmddyyyyRegex.MatchString(s):
		return calculateFullDate(mmddyyyyRegex.FindStringSubmatch(s), opts, 4, 2, 3)
	case ddmmyyRegex.MatchString(s):
		return calculateFullDate(ddmmyyRegex.FindStringSubmatch(s), opts, 4, 3, 2)
	case mmddyyRegex.MatchString(s):
		return calculateFullDate(mmddyyRegex.FindStringSubmatch(s), opts, 4, 2, 3)
	case isoyyyymmddRegex.MatchString(s):
		return calculateFullDate(isoyyyymmddRegex.FindStringSubmatch(s), opts, 2, 3, 4)
	case isoyymmddRegex.MatchString(s):
		return calculateFullDate(isoyymmddRegex.FindStringSubmatch(s), opts, 2, 3, 4)
	case ddMonthRegex.MatchString(s):
		return calculateDate(ddMonthRegex.FindStringSubmatch(s), opts, 3, 1)
	case ddmmRegex.MatchString(s):
		return calculateDate(ddmmRegex.FindStringSubmatch(s), opts, 3, 2)
	case mmddRegex.MatchString(s):
		return calculateDate(mmddRegex.FindStringSubmatch(s), opts, 2, 3)
	case wdsTimeRegex.MatchString(s):
		m := wdsTimeRegex.FindStringSubmatch(s)
		date := getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day(), forceInt(m[2]), 0, 0, opts)
		if date.Before(opts.Now) {
			date = date.Add(24 * time.Hour)
		}
		return date, m[0]
	case baseDurTimeRegex.MatchString(s):
		return calculateDuration(baseDurTimeRegex.FindStringSubmatch(s), opts, 1)
	case wdsRegex.MatchString(s):
		return calculateWordsDate(wdsRegex.FindStringSubmatch(s), opts)
	case ddRegex.MatchString(s):
		m := ddRegex.FindStringSubmatch(s)
		day := forceInt(m[2])
		return getDate(opts.Now.Year(), opts.Now.Month(), day, opts.TodayEndHour, 0, 0, opts), m[0]
	}
	return opts.Now, st
}

func getDate(year int, month time.Month, day int, hour int, minute int, second int, opts Opts) time.Time {
	return time.Date(year, month, day, hour, minute, second, 0, opts.Now.Location())
}

func calculateDate(m []string, opts Opts, monthPosition int, dayPosition int) (time.Time, string) {
	month := opts.Now.Month()
	if mth := parseMonth(m[monthPosition]); mth != 0 {
		month = mth
	} else {
		month = time.Month(forceInt(m[monthPosition]))
	}

	year := opts.Now.Year()
	if month < opts.Now.Month() {
		year++
	}

	day := forceInt(m[dayPosition])
	return getDate(year, month, day, opts.TodayEndHour, 0, 0, opts), m[0]
}

func calculateFullDate(m []string, opts Opts, yearPosition int, monthPosition int, dayPosition int) (time.Time, string) {
	year := opts.Now.Year()
	if len(m[yearPosition]) == 2 {
		year = forceInt("20" + m[yearPosition][:2])
	} else {
		year = forceInt(m[yearPosition][:4])
	}
	date, _ := calculateDate(m, opts, monthPosition, dayPosition)
	if date.Month() < opts.Now.Month() && year == opts.Now.Year() {
		year += 1
	}
	return getDate(year, date.Month(), date.Day(), opts.TodayEndHour, 0, 0, opts), m[0]
}

func calculateWordsDate(m []string, opts Opts) (time.Time, string) {
	m = normalizeStrings(m)
	date := getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day(), opts.Now.Hour(), opts.Now.Minute(), 0, opts)
	str := strings.Replace(m[0], "/", "", 1)
	switch {
	case strings.Contains(today, str) || strings.Contains(today, m[1]):
		date = getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day(), opts.TodayEndHour, 0, 0, opts)
	case strings.Contains(tomorrow, str) || strings.Contains(tomorrow, m[1]):
		date = getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day()+1, opts.TodayEndHour, 0, 0, opts)
	case strings.Contains(afterTomorrow, m[0]):
		date = getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day()+2, opts.TodayEndHour, 0, 0, opts)
	case strings.Contains(afterAfterTomorrow, m[0]):
		date = getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day()+3, opts.TodayEndHour, 0, 0, opts)
	case strings.Contains(yesterday, m[0]):
		date = getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day()+365, opts.TodayEndHour, 0, 0, opts)
	}
	if len(m) > 2 {
		switch {
		case strings.Contains(morning, m[2]):
			date = getDate(date.Year(), date.Month(), date.Day(), 10, 0, 0, opts)
		case strings.Contains(noon, m[2]):
			date = getDate(date.Year(), date.Month(), date.Day(), 12, 0, 0, opts)
		case strings.Contains(evening, m[2]):
			date = getDate(date.Year(), date.Month(), date.Day(), 18, 0, 0, opts)
		case strings.Contains(midnight, m[2]):
			if date.Day() == opts.Now.Day() {
				date = date.Add(24 * time.Hour)
			}
			date = getDate(date.Year(), date.Month(), date.Day(), 0, 0, 0, opts)
		}
	}
	if len(m) > 3 {
		switch {
		case strings.Contains(noon, m[3]):
			date = getDate(date.Year(), date.Month(), date.Day(), 12, 0, 0, opts)
		case strings.Contains(midnight, m[3]):
			if date.Day() == opts.Now.Day() {
				date = date.Add(24 * time.Hour)
			}
			date = getDate(date.Year(), date.Month(), date.Day(), 0, 0, 0, opts)
		}
	}

	return date, m[0]
}


text:
package dateparse

import (
	"testing"
	"time"
)

type parserStruct struct {
	date    time.Time
	message string
}

func TestDateparse(t *testing.T) {
	loc, err := time.LoadLocation("Europe/Moscow")
	if err != nil {
		t.Fatal("load location fail:", err)
	}
	dt := time.Date(2020, 10, 10, 12, 1, 0, 0, loc) // saturday
	for k, want := range map[string]parserStruct{
		"через час тест": {
			dt.Add(1 * time.Hour),
			"тест",
		},
		"в 15 часов": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 15, 0, 0, 0, dt.Location()),
			"",
		},
		"в 11 часов": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 11, 0, 0, 0, dt.Location()),
			"",
		},
		"at 11 hours": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 11, 0, 0, 0, dt.Location()),
			"",
		},
		"в 11 комментарий": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 11, 0, 0, 0, dt.Location()),
			"комментарий",
		},
		"сегодня/13:00 почитать": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 13, 0, 0, 0, dt.Location()),
			"почитать",
		},
		"завтра/13:00": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 13, 0, 0, 0, dt.Location()),
			"",
		},
		"сегодня в полночь": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 0, 0, 0, 0, dt.Location()),
			"",
		},
		"послезавтра днем": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+2, 12, 0, 0, 0, dt.Location()),
			"",
		},
		"at midnight": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 0, 0, 0, 0, dt.Location()),
			"",
		},
		"tomorrow at midnight eat": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 0, 0, 0, 0, dt.Location()),
			"eat",
		},
		"завтра в полночь": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 0, 0, 0, 0, dt.Location()),
			"",
		},
		"послезавтра ночью": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+2, 0, 0, 0, 0, dt.Location()),
			"",
		},
		"сегодня в 22:00 тестируем": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 22, 0, 0, 0, dt.Location()),
			"тестируем",
		},
		"сегодня в 18:00 умыться": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 18, 0, 0, 0, dt.Location()),
			"умыться",
		},
		"сегодня в 18": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 18, 0, 0, 0, dt.Location()),
			"",
		},
		"ровно через год": {
			dt.Add(24 * 365 * time.Hour),
			"",
		},
		"пнуть женю в 16:00": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 16, 0, 0, 0, dt.Location()),
			"пнуть женю",
		},
		"в 11 утра": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 11, 0, 0, 0, dt.Location()),
			"",
		},
		" в 11 вечера покодить": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 23, 0, 0, 0, dt.Location()),
			"покодить",
		},
		"в 22:00 спать": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 22, 0, 0, 0, dt.Location()),
			"спать",
		},
		"в 18:00 декомпозировать": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 18, 0, 0, 0, dt.Location()),
			"декомпозировать",
		},
		"05.09.2019 в 12:00": {
			time.Date(2019, 9, 5, 12, 0, 0, 0, dt.Location()),
			"",
		},
		"05.09.2019/13:00": {
			time.Date(2019, 9, 5, 13, 0, 0, 0, dt.Location()),
			"",
		},
		"05/26/2021": {
			time.Date(2021, 5, 26, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"05/26/22": {
			time.Date(2022, 5, 26, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"05/26": {
			time.Date(dt.Year()+1, 5, 26, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"26/05/22": {
			time.Date(2022, 5, 26, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"09.07 в 12:00": {
			time.Date(dt.Year()+1, 7, 9, 12, 0, 0, 0, dt.Location()),
			"",
		},
		"1 августа": {
			time.Date(dt.Year()+1, 8, 1, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"23 июня в 9 утра": {
			time.Date(dt.Year()+1, 6, 23, 9, 0, 0, 0, dt.Location()),
			"",
		},
		"1 июля": {
			time.Date(dt.Year()+1, 7, 1, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"31 сентября": {
			time.Date(dt.Year()+1, 9, 31, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"15 ноября выпить молока": {
			time.Date(dt.Year(), 11, 15, 18, 0, 0, 0, dt.Location()),
			"выпить молока",
		},
		"15 октября": {
			time.Date(dt.Year(), 10, 15, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"12/13": {
			time.Date(dt.Year(), 12, 13, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"12:13 проверить что-то": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 12, 13, 0, 0, dt.Location()),
			"проверить что-то",
		},
		"16.16": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 16, 16, 0, 0, dt.Location()),
			"",
		},
		"30th morning chil": {
			time.Date(dt.Year(), dt.Month(), 30, 10, 0, 0, 0, dt.Location()),
			"chil",
		},
		"30-го чил": {
			time.Date(dt.Year(), dt.Month(), 30, 18, 0, 0, 0, dt.Location()),
			"чил",
		},
		"18 июня в 14:00 на море": {
			time.Date(dt.Year()+1, 6, 18, 14, 0, 0, 0, dt.Location()),
			"на море",
		},
		"18.03.2019 12:00": {
			time.Date(2019, 3, 18, 12, 0, 0, 0, dt.Location()),
			"",
		},
		"20 марта 2020 года": {
			time.Date(2021, 3, 20, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"20 марта 2021 года купить дошик": {
			time.Date(2021, 3, 20, 18, 0, 0, 0, dt.Location()),
			"купить дошик",
		},
		"20 марта 21 года": {
			time.Date(2021, 3, 20, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"20 мая": {
			time.Date(dt.Year()+1, 5, 20, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"31 мая": {
			time.Date(dt.Year()+1, 5, 31, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"20.11.2019к 9:45 посетить врача": {
			time.Date(2019, 11, 20, 9, 45, 0, 0, dt.Location()),
			"посетить врача",
		},
		"21.09 14:00 чильнуть": {
			time.Date(dt.Year()+1, 9, 21, 14, 0, 0, 0, dt.Location()),
			"чильнуть",
		},
		"23 14:00 поужинать в кафе": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 14, 0, 0, 0, dt.Location()),
			"23  поужинать в кафе",
		},
		"23-ого в 14:00 срезы": {
			time.Date(dt.Year(), dt.Month(), 23, 14, 0, 0, 0, dt.Location()),
			"срезы",
		},
		"23 числа в 14:00 др начальника": {
			time.Date(dt.Year(), dt.Month(), 23, 14, 0, 0, 0, dt.Location()),
			"др начальника",
		},
		"23/12 в 14 тренировка": {
			time.Date(dt.Year(), 12, 23, 14, 0, 0, 0, dt.Location()),
			"тренировка",
		},
		"23/12 14:00 тренировка 2": {
			time.Date(dt.Year(), 12, 23, 14, 0, 0, 0, dt.Location()),
			"тренировка 2",
		},
		"25.04 в 14 проснуться": {
			time.Date(dt.Year()+1, 4, 25, 14, 0, 0, 0, dt.Location()),
			"проснуться",
		},
		"26.09. 12:00 улыбнуться": {
			time.Date(dt.Year()+1, 9, 26, 12, 0, 0, 0, dt.Location()),
			"улыбнуться",
		},
		"31.05.2019 спектакль": {
			time.Date(2019, 5, 31, 18, 0, 0, 0, dt.Location()),
			"спектакль",
		},
		"7:00 завтрак": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 7, 0, 0, 0, dt.Location()),
			"завтрак",
		},
		"в 10 выпить кофан": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 10, 0, 0, 0, dt.Location()),
			"выпить кофан",
		},
		"в 16:59 позвонить": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 16, 59, 0, 0, dt.Location()),
			"позвонить",
		},
		"в 1:30": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 1, 30, 0, 0, dt.Location()),
			"",
		},
		"в понедельник убраться": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+2, 18, 0, 0, 0, dt.Location()),
			"убраться",
		},
		"в следующий понедельник": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+9, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"в следующий понедельник утром посмотреть код": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+9, 10, 0, 0, 0, dt.Location()),
			"посмотреть код",
		},
		"в субботу утром": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+7, 10, 0, 0, 0, dt.Location()),
			"",
		},
		"утром": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 10, 0, 0, 0, dt.Location()),
			"",
		},
		"вечером": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 18, 0, 0, 0, dt.Location()),
			"",
		},
		"понедельник через два дома офис": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+2, 18, 0, 0, 0, dt.Location()),
			"через два дома офис",
		},
		"утром в субботу почистить зубы": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+7, 10, 0, 0, 0, dt.Location()),
			"почистить зубы",
		},
		"в полночь в понедельник помыть голову": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+2, 0, 0, 0, 0, dt.Location()),
			"помыть голову",
		},
		"в субботу": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 18, 0, 0, 0, dt.Location()),
			"",
		},
		"on monday test": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+2, 18, 0, 0, 0, dt.Location()),
			"test",
		},
		"on monday at 5 p.m": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+2, 17, 0, 0, 0, dt.Location()),
			"",
		},
		"в пятницу в 5 утра": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+6, 5, 0, 0, 0, dt.Location()),
			"",
		},
		"в пятницу в 5 вечера на волгу": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+6, 17, 0, 0, 0, dt.Location()),
			"на волгу",
		},
		"в среду": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+4, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"в пн": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+2, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"пн": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+2, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"вт": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+3, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"ср": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+4, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"чт": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+5, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"пт": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+6, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"сб": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 18, 0, 0, 0, dt.Location()),
			"",
		},
		"вс": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"вс тестируем приложение": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 18, 0, 0, 0, dt.Location()),
			"тестируем приложение",
		},
		"в полдень покушать": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 12, 0, 0, 0, dt.Location()),
			"покушать",
		},
		"четверговый митап завтра": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 18, 0, 0, 0, dt.Location()),
			"четверговый митап",
		},
		"что завтра совещание": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 18, 0, 0, 0, dt.Location()),
			"что  совещание",
		},
		"в полночь": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 0, 0, 0, 0, dt.Location()),
			"",
		},
		"среду": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+4, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"в среду в 12:30": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+4, 12, 30, 0, 0, dt.Location()),
			"",
		},
		"в среду утром": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+4, 10, 0, 0, 0, dt.Location()),
			"",
		},
		"во вторник": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+3, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"вчера": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+365, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"завтра в 12": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 12, 0, 0, 0, dt.Location()),
			"",
		},
		"завтра воскресный праздник": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 18, 0, 0, 0, dt.Location()),
			"воскресный праздник",
		},
		"09.12": {
			time.Date(dt.Year(), 12, 9, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"09/12": {
			time.Date(dt.Year(), 12, 9, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"09/12/2050 продать": {
			time.Date(2050, 12, 9, 18, 0, 0, 0, dt.Location()),
			"продать",
		},
		"2020-04-25": {
			time.Date(2021, 4, 25, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"2020-0809": {
			time.Date(2021, 8, 9, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"20-0809": {
			time.Date(2021, 8, 9, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"2020-0809 потеряли дефис": {
			time.Date(2021, 8, 9, 18, 0, 0, 0, dt.Location()),
			"потеряли дефис",
		},
		"2020-04-25 это Iso формат": {
			time.Date(2021, 4, 25, 18, 0, 0, 0, dt.Location()),
			"это iso формат",
		},
		"20-04-25": {
			time.Date(2021, 4, 25, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"200425": {
			time.Date(2021, 4, 25, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"20200425": {
			time.Date(2021, 4, 25, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"20200425 потеряли все": {
			time.Date(2021, 4, 25, 18, 0, 0, 0, dt.Location()),
			"потеряли все",
		},
		"20-04-25 покормить собаку": {
			time.Date(2021, 4, 25, 18, 0, 0, 0, dt.Location()),
			"покормить собаку",
		},
		"10/02/50-го покушать": {
			time.Date(2050, 2, 10, 18, 0, 0, 0, dt.Location()),
			"покушать",
		},
		"сегодня": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 18, 0, 0, 0, dt.Location()),
			"",
		},
		"сегодня сохранить фото": {
			time.Date(dt.Year(), dt.Month(), dt.Day(), 18, 0, 0, 0, dt.Location()),
			"сохранить фото",
		},
		"30 минут кофе": {
			dt.Add(30 * time.Minute),
			"кофе",
		},
		"завтра": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"завтра через неделю поход": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 18, 0, 0, 0, dt.Location()),
			"через неделю поход",
		},
		"завтра в среду важное совещание": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 18, 0, 0, 0, dt.Location()),
			"в среду важное совещание",
		},
		"послезавтра помыть голову": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+2, 18, 0, 0, 0, dt.Location()),
			"помыть голову",
		},
		"послепослезавтра": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+3, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"after tomorrow": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+2, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"через 1 минуту моргнуть": {
			dt.Add(1 * time.Minute),
			"моргнуть",
		},
		"in 1 min": {
			dt.Add(1 * time.Minute),
			"",
		},
		"через 3 недели": {
			dt.Add(3 * 7 * 24 * time.Hour),
			"",
		},
		"через 3 неделя": {
			dt.Add(3 * 7 * 24 * time.Hour),
			"",
		},
		"1 неделя": {
			dt.Add(7 * 24 * time.Hour),
			"",
		},
		"1 week wake up": {
			dt.Add(7 * 24 * time.Hour),
			"wake up",
		},
		"через 10 недель": {
			dt.Add(10 * 7 * 24 * time.Hour),
			"",
		},
		"через 30": {
			dt.Add(30 * time.Minute),
			"",
		},
		"через 30 секунд куку": {
			dt.Add(30 * time.Second),
			"куку",
		},
		"через 6 часов": {
			dt.Add(6 * time.Hour),
			"",
		},
		"через 2 часа": {
			dt.Add(2 * time.Hour),
			"",
		},
		"через 7 дней": {
			dt.Add(7 * 24 * time.Hour),
			"",
		},
		"через 2 дня": {
			dt.Add(2 * 24 * time.Hour),
			"",
		},
		"через 100 дней отдохнуть": {
			dt.Add(100 * 24 * time.Hour),
			"отдохнуть",
		},
		"через год": {
			dt.Add(365 * 24 * time.Hour),
			"",
		},
		"через месяц": {
			dt.Add(31 * 24 * time.Hour),
			"",
		},
		"через минуту": {
			dt.Add(1 * time.Minute),
			"",
		},
		"через минуту [username](http://ya.ru)": {
			dt.Add(1 * time.Minute),
			"[username](http://ya.ru)",
		},
		"через 2 минуты": {
			dt.Add(2 * time.Minute),
			"",
		},
		"через неделю выходной": {
			dt.Add(7 * 24 * time.Hour),
			"выходной",
		},
		"через два часа": {
			dt.Add(2 * time.Hour),
			"",
		},
		"через три дня сходить в кино": {
			dt.Add(3 * 24 * time.Hour),
			"сходить в кино",
		},
		"в следующую субботу": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+7, 18, 0, 0, 0, dt.Location()),
			"",
		},
		"в следующую субботу праздник": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+7, 18, 0, 0, 0, dt.Location()),
			"праздник",
		},
		"с утра тест": {
			time.Date(dt.Year(), dt.Month(), dt.Day()+1, 10, 0, 0, 0, dt.Location()),
			"тест",
		},
		"через три минуты тест": {
			dt.Add(time.Minute * 3),
			"тест",
		},
		"через пол часа тест": {
			dt.Add(time.Minute * 30),
			"тест",
		},
		"через четверть минуты тест": {
			dt.Add(time.Second * 15),
			"тест",
		},
		"через полчаса тест": {
			dt.Add(time.Minute * 30),
			"тест",
		},
		// FIXME:
		//"в субботу в 11 утра": {
		//	time.Date(dt.Year(), dt.Month(), dt.Day()+7, 11, 0, 0, 0, dt.Location()),
		//	"",
		//},
		//"12 13": {
		//	time.Date(dt.Year(), dt.Month(), dt.Day(), 12, 13, 0, 0, dt.Location()),
		//	"",
		//},
		//"20.11/13:00": {
		//	time.Date(dt.Year(), 11, 20, 13, 0, 0, 0, dt.Location()),
		//	 "",
		//},
		//"завтра про полдень в": {
		//	dt.Add(24 * time.Hour),
		//	"",
		//},
		//"09 00": {
		//	time.Date(dt.Year(), dt.Month(), dt.Day()+1, 9, 0, 0, 0, dt.Location()),
		//	"",
		//},
		//"15": {
		//	time.Date(dt.Year(), dt.Month(), dt.Day(), 15, 0, 0, 0, dt.Location()),
		//	"",
		//},
		//"2": {
		//	time.Date(dt.Year(), dt.Month(), dt.Day()+1, 2, 0, 0, 0, dt.Location()),
		//	"",
		//},
		//"9 14": {
		//	time.Date(dt.Year(), dt.Month(), dt.Day()+1, 9, 14, 0, 0, dt.Location()),
		//	"",
		//},
	} {
		t.Run(k, func(t *testing.T) {
			got, msg := Parse(k, &Opts{Now: dt})
			if got.IsZero() || !got.Equal(want.date) || msg != want.message {
				t.Errorf("dateparse error on '%s': got '%s' (comment: '%s') want '%s' (comment: '%s')", k, got, msg, want.date, want.message)
			}
		})
	}
}

// BenchmarkParse-12    	   15781	     76097 ns/op	     494 B/op	      14 allocs/op
// ==>
// BenchmarkParse-12    	   16088	     75671 ns/op	     439 B/op	       8 allocs/op
func BenchmarkParse(b *testing.B) {
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		Parse("сегодня в 18", nil)
	}
}


text:
package dateparse

import (
	"testing"
)

func TestCheckWordNumber(t *testing.T) {
	for _, tt := range []struct {
		input  string
		output float64
	}{
		{
			"пол",
			0.5,
		},
		{
			"четверть",
			0.25,
		},
	} {
		result := checkWordNumber(tt.input)
		if result != tt.output {
			t.Errorf("%v != %v", result, tt.output)
		}
	}
}


text:
package dateparse

import (
	"strings"
	"time"
)

var (
	sunday    = `воскресенье|sunday`
	monday    = `понедельник|monday`
	tuesday   = `вторник|tuesday`
	wednesday = `среду|среда|wednesday`
	thursday  = `четверг|thursday`
	friday    = `пятницу|пятница|friday`
	saturday  = `субботу|суббота|saturday`
	weeks     = strings.Join([]string{
		sunday,
		monday,
		tuesday,
		wednesday,
		thursday,
		friday,
		saturday,
	}, "|")
)

var (
	shortSunday    = `вс|воскр|sun`
	shortMonday    = `пн|пнд|понед|mon`
	shortTuesday   = `вт|thu`
	shortWednesday = `ср|wed`
	shortThursday  = `чт|thu`
	shortFriday    = `пт|fri`
	shortSaturday  = `сб|sat`
	shortWeeks     = strings.Join([]string{
		shortSunday,
		shortMonday,
		shortTuesday,
		shortWednesday,
		shortThursday,
		shortFriday,
		shortSaturday,
	}, "|")
)

func parseWeekDay(s string, opts Opts) time.Time {
	date := getDate(opts.Now.Year(), opts.Now.Month(), opts.Now.Day(), opts.TodayEndHour, 0, 0, opts)
	if weakDay := parseWeekDays(s); weakDay < 7 {
		v := weakDay - int(date.Weekday())
		if v < 0 {
			date = date.Add(time.Duration(v)*24*time.Hour + 7*24*time.Hour)
		} else {
			date = date.Add(time.Duration(v) * 24 * time.Hour)
		}
	}
	return date
}

func parseWeekDays(s string) int {
	switch {
	case strings.Contains(strings.Join([]string{sunday, shortSunday}, "|"), s):
		return 0
	case strings.Contains(strings.Join([]string{monday, shortMonday}, "|"), s):
		return 1
	case strings.Contains(strings.Join([]string{tuesday, shortTuesday}, "|"), s):
		return 2
	case strings.Contains(strings.Join([]string{wednesday, shortWednesday}, "|"), s):
		return 3
	case strings.Contains(strings.Join([]string{thursday, shortThursday}, "|"), s):
		return 4
	case strings.Contains(strings.Join([]string{friday, shortFriday}, "|"), s):
		return 5
	case strings.Contains(strings.Join([]string{saturday, shortSaturday}, "|"), s):
		return 6
	}
	return 7
}

func calculateWeekDuration(m []string, opts Opts, weekPosition int) (time.Time, string) {
	timePosition := weekPosition + 1
	if weekPosition < 0 {
		weekPosition = len(m) - 1
		timePosition = weekPosition - 2
	}
	date := parseWeekDay(m[weekPosition], opts)
	switch {
	case strings.Contains(durPrefix, m[weekPosition-1]):
		date = date.Add(24 * 7 * time.Hour)
	}
	if len(m) > 3 {
		switch {
		case strings.Contains(morning, m[timePosition]) && m[timePosition] != "":
			if date.Weekday() == opts.Now.Weekday() && opts.Now.Hour() > 10 {
				date = date.Add(24 * 7 * time.Hour)
			}
			return getDate(date.Year(), date.Month(), date.Day(), 10, 0, 0, opts), m[0]
		case strings.Contains(evening, m[timePosition]) && m[timePosition] != "":
			return date, m[0]
		case strings.Contains(noon, m[timePosition]) && m[timePosition] != "":
			return getDate(date.Year(), date.Month(), date.Day(), 12, 0, 0, opts), m[0]
		case strings.Contains(midnight, m[timePosition]) && m[timePosition] != "":
			return getDate(date.Year(), date.Month(), date.Day(), 0, 0, 0, opts), m[0]
		}
	}
	if date.Before(opts.Now) {
		date = date.Add(7 * 24 * time.Hour)
	}
	return date, m[0]
}


text:
module github.com/tada-team/dateparse

go 1.14


text:
package dateparse

import (
	"math/rand"
	"regexp"
	"strings"
	"time"
)

var dateTimeRegex, _ = joinRegexp([]*regexp.Regexp{baseDurOnlyRegex, baseWeekOnlyRegex, baseWeekPrefixRegex, baseWeekPrefixOnlyRegex,
	baseDurRegex, baseWeekRegex, baseTimeOrientationRegex, durTimeRegex, baseDurTimeRegex, durRegex, wdsSuffuxRegex, wdsRegex,
	ddRegex, ddmmRegex, ddMonthRegex, ddmmyyyyRegex, mmddyyyyRegex, mmddRegex, ddMonthyyyyRegex, ddmmyyRegex, mmddyyRegex,
	ddMonthyyRegex, durPrefixWeekRegex, weekDurSuffixRegex, durSuffixWeekRegex, hhmmRegex, hhRegex, isoyyyymmddRegex, isoyymmddRegex, wdsTimeRegex}, "|")

func dateTimeParse(s string, opts Opts) (t time.Time, msg string) {
	if dateTimeRegex.MatchString(s) {

		marker := getMarker()
		s = strings.ReplaceAll(s, "://", marker)

		date, replacingDate := parseDate(s, opts)
		s = strings.Replace(s, strings.TrimSpace(replacingDate), "", 1)
		timeP, replacingTime := parseTime(s, opts)
		if (timeP.Before(opts.Now) || timeP == opts.Now) && date == opts.Now {
			date = date.Add(24 * time.Hour)
		}

		hour := timeP.Hour()
		minute := timeP.Minute()
		second := timeP.Second()

		replacingTime = strings.TrimSpace(replacingTime)
		if len(replacingTime) == 0 {
			hour = date.Hour()
			minute = date.Minute()
			second = date.Second()
		}

		s = strings.Replace(s, replacingTime, "", 1)
		s = strings.ReplaceAll(s, marker, "://")

		return getDate(date.Year(), date.Month(), date.Day(), hour, minute, second, opts), strings.TrimSpace(s)
	}
	return
}

func joinRegexp(regexps []*regexp.Regexp, sep string) (*regexp.Regexp, error) {
	var b strings.Builder
	for i, re := range regexps {
		if i > 0 {
			b.WriteString(sep)
		}
		b.WriteString(re.String())
	}
	return regexp.Compile(b.String())
}

func getMarker() string {
	b := make([]byte, 20)
	rand.Read(b)
	return string(b)
}


text:
package dateparse

import (
	"strconv"
	"strings"
)

func forceInt(s string) int { return int(forceInt64(s)) }

func forceInt64(s string) int64 {
	s = strings.TrimSpace(s)
	s = strings.TrimLeft(s, "0")
	if s == "" {
		return 0
	}
	val, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		return 0
	}
	return val
}

func forceFloat64(s string) float64 {
	s = strings.TrimSpace(s)
	s = strings.TrimLeft(s, "0")
	if s == "" {
		return 0
	}
	val, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return 0
	}
	return val
}

func normalizeStrings(ss []string) []string {
	if len(ss) <= 1 {
		return ss
	}
	res := make([]string, 0, len(ss))
	for _, bit := range ss {
		bit = strings.TrimSpace(bit)
		if bit != "" {
			res = append(res, bit)
		}
	}
	return res
}


text:
package dateparse

import (
	"strings"
	"time"
)

var (
	january   = `января|янв|january|jan`
	february  = `февраля|фев|february|feb`
	march     = `марта|мар|march|mar`
	april     = `апреля|апрель|апр|april|apr`
	may       = `мая|май|may`
	june      = `июня|июнь|june|jun`
	july      = `июля|июль|july|jul`
	august    = `августа|август|august|aug`
	september = `сентября|сентябрь|сент|september|sep`
	october   = `октября|октябрь|october|oct`
	november  = `ноября|ноябрь|november|nov`
	december  = `декабря|дек|december|dec`
	months    = strings.Join([]string{january, february, march, april, may, june, july, august, september, october, november, december}, "|")
)

func parseMonth(monthStr string) time.Month {
	switch {
	case strings.Contains(january, monthStr):
		return 1
	case strings.Contains(february, monthStr):
		return 2
	case strings.Contains(march, monthStr):
		return 3
	case strings.Contains(april, monthStr):
		return 4
	case strings.Contains(may, monthStr):
		return 5
	case strings.Contains(june, monthStr):
		return 6
	case strings.Contains(july, monthStr):
		return 7
	case strings.Contains(august, monthStr):
		return 8
	case strings.Contains(september, monthStr):
		return 9
	case strings.Contains(october, monthStr):
		return 10
	case strings.Contains(november, monthStr):
		return 11
	case strings.Contains(december, monthStr):
		return 12
	}
	return 0
}


text:
package dateparse

import (
	"strings"
	"time"
)

type Opts struct {
	TodayEndHour int
	Now          time.Time
}

func Parse(s string, opts *Opts) (time.Time, string) {
	if opts == nil {
		opts = new(Opts)
	}
	if opts.TodayEndHour == 0 {
		opts.TodayEndHour = 18
	}
	date, msg := dateTimeParse(strings.TrimSpace(strings.ToLower(s)), *opts)
	return date.Round(time.Second), msg
}


text:
package dateparse

import (
	"strings"
	"time"
)

var (
	seconds           = `сек|секунд|sec|seconds`
	minutes           = `мин|минут|минуту|минуты|min`
	hours             = `часов|hours|hour|часа|час`
	days              = `дней|дня|days`
	weeksWords        = `недель|неделю|недели|неделя|weeks|week`
	monthsWords       = `месяцев|месяца|month`
	years             = `лет|года|год|years`
	durationTimeWords = strings.Join([]string{seconds, minutes, hours, days, weeksWords, monthsWords, years}, "|")
)

var (
	durPrefix      = `(через|in|следующ[и]?[й]?[у]?[ю]?|следующий|следующую|next)`
	duration       = strings.Join([]string{today, tomorrow, afterTomorrow, afterAfterTomorrow, yesterday}, "|")
	durationTime   = `сек[у]?[н]?[д]?[а]?[у]?|мин[у]?[т]?[у]?[а]?[ы]?|min[u]?[t]?[e]?[s]?|час[о]?[в]?[а]?|hour[s]?|дн[е]?[й]?[я]?|day[s]?|недел[ь]?[я]?[и]?[ю]?|week[s]?|год|year[s]?|месяц[а]?[е]?[в]?|month[s]?`
	durationWds    = strings.Join([]string{duration, durationTime}, "|")
	durationSuffix = `(утр[а]?[о]?[м]?|morning|вечер[а]?[о]?[м]?|evening|\\|/|днем|полдень|полночь|midday|noon|midnight|ночью)`
)

var (
	quarter     = `quarter|четверть`
	half        = `half|пол`
	one         = `one|один`
	two         = `two|два`
	three       = `three|три`
	four        = `four|четыре`
	five        = `five|пять`
	six         = `six|шесть`
	seven       = `seven|семь`
	eight       = `eight|восемь`
	nine        = `nine|девять`
	ten         = `ten|десять`
	wordNumbers = strings.Join([]string{quarter, half, one, two, three, four, five, six, seven, eight, nine, ten}, "|")
)

func checkWordNumber(s string) float64 {
	if v := forceFloat64(s); v != 0 {
		return v
	}
	switch {
	case strings.Contains(quarter, s):
		return 0.25
	case strings.Contains(half, s):
		return 0.5
	case strings.Contains(one, s):
		return 1
	case strings.Contains(two, s):
		return 2
	case strings.Contains(three, s):
		return 3
	case strings.Contains(four, s):
		return 4
	case strings.Contains(five, s):
		return 5
	case strings.Contains(six, s):
		return 6
	case strings.Contains(seven, s):
		return 7
	case strings.Contains(eight, s):
		return 8
	case strings.Contains(nine, s):
		return 9
	case strings.Contains(ten, s):
		return 10
	}
	return 0
}

func calculateDuration(m []string, opts Opts, k int) (time.Time, string) {
	dur := durationParse(m[k:], opts)
	if dur > 0 {
		return opts.Now.Add(dur).In(opts.Now.Location()), m[0]
	}
	return opts.Now, m[0]
}

func durationParse(bits []string, opts Opts) (dur time.Duration) {
	if strings.Contains(durPrefix, bits[0]) {
		return durationParse(normalizeStrings(bits[1:]), opts)
	}

	switch len(bits) {
	case 1:
		word := bits[0]
		switch {
		case strings.Contains(durationTimeWords, word):
			return durationParse([]string{"1", word}, opts)
		}
		if forceInt64(word) > 0 {
			return durationParse([]string{word, "минут"}, opts)
		}
	case 2:
		v := checkWordNumber(bits[0])
		if v == 0 {
			return
		}
		word := strings.TrimSpace(bits[1])
		if v < 1 && v >= 0 {
			div := time.Duration(1 / v)
			switch {
			case strings.Contains(seconds, word):
				return time.Second / div
			case strings.Contains(minutes, word):
				return time.Minute / div
			case strings.Contains(hours, word):
				return time.Hour / div
			case strings.Contains(days, word):
				return time.Hour * 12
			case strings.Contains(weeksWords, word):
				return time.Hour * 12 * 7
			case strings.Contains(monthsWords, word):
				return time.Hour * 12 * 31 // XXX:
			case strings.Contains(years, word):
				return time.Hour * 12 * 365 // XXX:
			default:
				return durationParse(bits[:1], opts)
			}
		}

		switch {
		case strings.Contains(seconds, word):
			return time.Duration(v) * time.Second
		case strings.Contains(minutes, word):
			return time.Duration(v) * time.Minute
		case strings.Contains(hours, word):
			return time.Duration(v) * time.Hour
		case strings.Contains(days, word):
			return time.Duration(v) * time.Hour * 24
		case strings.Contains(weeksWords, word):
			return time.Duration(v) * time.Hour * 24 * 7
		case strings.Contains(monthsWords, word):
			return time.Duration(v) * time.Hour * 24 * 31 // XXX:
		case strings.Contains(years, word):
			return time.Duration(v) * time.Hour * 24 * 365 // XXX:
		default:
			return durationParse(bits[:1], opts)
		}
	}
	return
}


text:
[![Codecov coveragei build](https://github.com/tada-team/dateparse/actions/workflows/codecov.yml/badge.svg)](https://github.com/tada-team/dateparse/actions/workflows/codecov.yml) [![codecov](https://codecov.io/gh/tada-team/dateparse/branch/master/graph/badge.svg)](https://codecov.io/gh/tada-team/dateparse)
# dateparse

Лёгкий способ превратить пользовательский ввод даты во что-то машинопонятное.

Пользователи такие затейники, чего только не вводят, но мы пытаемся всё понять и простить:

```go
package main

import (
    "time"
    "github.com/tada-team/dateparse"
)

func main() {
    date, message := dateparse.Parse("в следующий понедельник утром посмотреть код", nil)
    if date.IsZero() {
        panic("invalid date")
    }
    print("at:", date)
    print("do:", message)

    loc, err := time.LoadLocation("Europe/Moscow")
    if err != nil {
        panic(err)
    }
    date, _ = dateparse.Parse("завтра", &dateparse.Opts{
        TodayEndHour: 20,
        Now:          time.Now().In(loc),
    })
    print(date)
}
```


text:
---
name: Codecov coverage

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-20.04
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-go@v2
        with:
          go-version: '1.14'
      - name: Run coverage
        run: go test -race -coverprofile=coverage.txt -covermode=atomic
      - name: Upload coverage to Codecov
        run: bash <(curl -s https://codecov.io/bash)


text:
/*
  This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScript’s language server to improve development experience.
  It is not intended to be used to perform a compilation.

  To learn more about this file see: https://angular.io/config/solution-tsconfig.
*/
{
  "files": [],
  "references": [
    {
      "path": "./src/tsconfig.app.json"
    },
    {
      "path": "./src/tsconfig.spec.json"
    },
    {
      "path": "./e2e/tsconfig.e2e.json"
    }
  ]
}

repo_language: TypeScript

mime_type: text/x-java


text:
# angular-multi-layout-scaffolding

![keep growing logo](readme-images/logo_250x60.png)

To learn how to set up a project like this one, check out the [Apply multi-layout to an Angular app](http://keepgrowing.in/angular/apply-multi-layout-to-an-angular-app/) post.

This application serves two separate layouts - one provided on a landing page view, the other used on a dashboard view. There is a horizontal navigation and a footer on the landing page and a vertical navigation on a dashboard.

All views are complemented with Bootstrap classes.

![landing page screenshot](readme-images/landing_page.png "Landing page")
![dashboard page screenshot](readme-images/dashboard_with_custom_sidenav.png "Dashboard page")

## Getting Started

To clone the repository, run in the command line:
```bash
$ git clone https://github.com/little-pinecone/angular-multi-layout-scaffolding.git
```

## Development server

Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.

## Build

Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.

## Running unit tests

Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).

## Built With

* [Angular 6](https://angular.io/) updated to [Angular 10](https://github.com/angular/angular/releases/tag/10.0.3)
* [Bootstrap 4](https://getbootstrap.com/)

## License

This project is licensed under the Unlicense - see the [license details](https://choosealicense.com/licenses/unlicense/).


text:
/**
 * This file includes polyfills needed by Angular and is loaded before the app.
 * You can add your own extra polyfills to this file.
 *
 * This file is divided into 2 sections:
 *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
 *   2. Application imports. Files imported after ZoneJS that should be loaded before your main
 *      file.
 *
 * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
 * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
 * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
 *
 * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
 */

/***************************************************************************************************
 * BROWSER POLYFILLS
 */

/** IE9, IE10 and IE11 requires all of the following polyfills. **/
// import 'core-js/es6/symbol';
// import 'core-js/es6/object';
// import 'core-js/es6/function';
// import 'core-js/es6/parse-int';
// import 'core-js/es6/parse-float';
// import 'core-js/es6/number';
// import 'core-js/es6/math';
// import 'core-js/es6/string';
// import 'core-js/es6/date';
// import 'core-js/es6/array';
// import 'core-js/es6/regexp';
// import 'core-js/es6/map';
// import 'core-js/es6/weak-map';
// import 'core-js/es6/set';

/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js';  // Run `npm install --save classlist.js`.

/** IE10 and IE11 requires the following for the Reflect API. */
// import 'core-js/es6/reflect';

/** Evergreen browsers require these. **/
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
import 'core-js/es7/reflect';

/**
 * Web Animations `@angular/platform-browser/animations`
 * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
 * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
 **/
// import 'web-animations-js';  // Run `npm install --save web-animations-js`.

/**
 * By default, zone.js will patch all possible macroTask and DomEvents
 * user can disable parts of macroTask/DomEvents patch by setting following flags
 */

 // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
 // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
 // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames

 /*
 * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
 * with the following flag, it will bypass `zone.js` patch for IE/Edge
 */
// (window as any).__Zone_enable_cross_context_check = true;

/***************************************************************************************************
 * Zone JS is required by default for Angular itself.
 */
import 'zone.js/dist/zone';  // Included with Angular CLI.

/***************************************************************************************************
 * APPLICATION IMPORTS
 */


text:
// This file is required by karma.conf.js and loads recursively all the .spec and framework files

import 'zone.js/dist/zone-testing';
import { getTestBed } from '@angular/core/testing';
import {
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';

declare const require: any;

// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting()
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);


text:
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    coverageIstanbulReporter: {
      dir: require('path').join(__dirname, '../coverage'),
      reports: ['html', 'lcovonly'],
      fixWebpackSourcePaths: true
    },
    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  });
};


text:
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>AngularMultiLayoutScaffolding</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root></app-root>
</body>
</html>


text:
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.log(err));


text:
/* You can add global styles to this file, and also import other style files */
html {
  height: 100%;
}
body {
  height: 100%;
}


text:
import { AppRoutingModule } from './app-routing.module';

describe('AppRoutingModule', () => {
  let appRoutingModule: AppRoutingModule;

  beforeEach(() => {
    appRoutingModule = new AppRoutingModule();
  });

  it('should create an instance', () => {
    expect(appRoutingModule).toBeTruthy();
  });
});


text:
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { RouterTestingModule } from '@angular/router/testing';
describe('AppComponent', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        AppComponent
      ],
      imports: [ RouterTestingModule ],
    }).compileComponents();
  }));
  it('should create the app', async(() => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app).toBeTruthy();
  }));
});


text:
import { NgModule } from '@angular/core';
import { RouterModule, Routes} from '@angular/router';

import { GuestLayoutComponent } from './layout/guest/guest-layout/guest-layout.component';
import { LandingPageComponent } from './pages/landing-page/landing-page.component';
import { AuthorisedLayoutComponent } from './layout/authorised/authorised-layout/authorised-layout.component';
import { DashboardComponent } from './pages/dashboard/dashboard.component';

const routes: Routes = [
  {
    path: '',
    component: GuestLayoutComponent,
    children: [
      { path: '', component: LandingPageComponent, pathMatch: 'full'},
    ]
  },
  {
    path: '',
    component: AuthorisedLayoutComponent,
    children: [
      { path: 'dashboard', component: DashboardComponent },
    ]
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [ RouterModule ]
})
export class AppRoutingModule { }


text: <router-outlet></router-outlet>


text:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { PageContentComponent } from './layout/page-content/page-content.component';
import { GuestTopNavComponent } from './layout/guest/guest-top-nav/guest-top-nav.component';
import { GuestFooterComponent } from './layout/guest/guest-footer/guest-footer.component';
import { GuestLayoutComponent } from './layout/guest/guest-layout/guest-layout.component';
import { LandingPageComponent } from './pages/landing-page/landing-page.component';
import { AppRoutingModule } from './/app-routing.module';
import { AuthorisedSideNavComponent } from './layout/authorised/authorised-side-nav/authorised-side-nav.component';
import { AuthorisedLayoutComponent } from './layout/authorised/authorised-layout/authorised-layout.component';
import { DashboardComponent } from './pages/dashboard/dashboard.component';
import { AuthorisedTopNavComponent } from './layout/authorised/authorised-top-nav/authorised-top-nav.component';
import { AuthorisedSideNavTogglerComponent } from './layout/authorised/authorised-side-nav-toggler/authorised-side-nav-toggler.component';

@NgModule({
  declarations: [
    AppComponent,
    PageContentComponent,
    GuestTopNavComponent,
    GuestFooterComponent,
    GuestLayoutComponent,
    LandingPageComponent,
    AuthorisedSideNavComponent,
    AuthorisedLayoutComponent,
    DashboardComponent,
    AuthorisedTopNavComponent,
    AuthorisedSideNavTogglerComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }


text:
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'app';
}


text:
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-landing-page',
  templateUrl: './landing-page.component.html',
  styleUrls: ['./landing-page.component.scss']
})
export class LandingPageComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}


text:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { LandingPageComponent } from './landing-page.component';

describe('LandingPageComponent', () => {
  let component: LandingPageComponent;
  let fixture: ComponentFixture<LandingPageComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ LandingPageComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(LandingPageComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
  it('should render main header in a h2 tag', async(() => {
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('h2').textContent).toContain('A simple landing page example');
  }));
  it('should render sub header in a h3 tag', async(() => {
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('h3').textContent).toContain('Lorem ipsum dolor sit amet');
  }));
  it('should render description in a p tag', async(() => {
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('p').textContent).toContain('Lorem ipsum dolor sit amet, consectetur adipiscing elit,');
  }));
  it('should render feature list', async(() => {
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('ul').textContent).toContain('Feature 1Feature 2Feature 3Feature 4');
  }));
});


text:
A simple landing page example

Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
        eiusmod tempor incididunt ut labore et dolore magna aliqua.
        Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
        nisi ut aliquip ex ea commodo consequat.

Feature 1

Feature 2

Feature 3

Feature 4


text:
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}


text:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { DashboardComponent } from './dashboard.component';

describe('DashboardComponent', () => {
  let component: DashboardComponent;
  let fixture: ComponentFixture<DashboardComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ DashboardComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(DashboardComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
  it('should render main header in a h2 tag', async(() => {
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('h2').textContent).toContain('Dashboard page');
  }));
});


text:
Dashboard page

          Featured

Special title treatment

With supporting text below as a natural lead-in to additional content.

          Go somewhere

          Featured

Special title treatment

With supporting text below as a natural lead-in to additional content.

          Go somewhere

Card title

Card subtitle

Some quick example text to build on the card title and make up the bulk of the card's content.

          Card link
          Another link

Card title

Card subtitle

Some quick example text to build on the card title and make up the bulk of the card's content.

          Card link
          Another link

Card title

Card subtitle

Some quick example text to build on the card title and make up the bulk of the card's content.

          Card link
          Another link

Card title

Card subtitle

Some quick example text to build on the card title and make up the bulk of the card's content.

          Card link
          Another link

Card title

Card subtitle

Some quick example text to build on the card title and make up the bulk of the card's content.

          Card link
          Another link


text:
.dashboard-cards {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content:flex-start;
  margin: 0 -15px;
  >.card {
    margin: 15px;
  }
}


text:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';

import { PageContentComponent } from './page-content.component';

describe('PageContentComponent', () => {
  let component: PageContentComponent;
  let fixture: ComponentFixture<PageContentComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ PageContentComponent ],
      imports: [ RouterTestingModule ],
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(PageContentComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});


text:
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-page-content',
  templateUrl: './page-content.component.html',
  styleUrls: ['./page-content.component.scss']
})
export class PageContentComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}


text:
:host {
  &.full-width {
    width: 100%;
  }
}


text:
.wrapper {
  display: flex;
  flex-direction: row;
}


text:
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-authorised-layout',
  templateUrl: './authorised-layout.component.html',
  styleUrls: ['./authorised-layout.component.scss']
})
export class AuthorisedLayoutComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}


text:
<app-authorised-top-nav></app-authorised-top-nav>
<div class="wrapper">
  <app-authorised-side-nav></app-authorised-side-nav>
  <app-page-content></app-page-content>
</div>


text:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { AuthorisedLayoutComponent } from './authorised-layout.component';

import { Component } from '@angular/core';

@Component({selector: 'app-authorised-side-nav', template: ''})
class AuthorisedSideNavComponent {}

@Component({selector: 'app-authorised-top-nav', template: ''})
class AuthorisedTopNavComponent {}

@Component({selector: 'app-page-content', template: ''})
class PageContentComponent { }

describe('AuthorisedLayoutComponent', () => {
  let component: AuthorisedLayoutComponent;
  let fixture: ComponentFixture<AuthorisedLayoutComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        AuthorisedLayoutComponent,
        AuthorisedSideNavComponent,
        AuthorisedTopNavComponent,
        PageContentComponent
      ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AuthorisedLayoutComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});


text:
import { TestBed, inject } from '@angular/core/testing';

import { AuthorisedSideNavService } from './authorised-side-nav.service';

describe('AuthorisedSideNavService', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [AuthorisedSideNavService]
    });
  });

  it('should be created', inject([AuthorisedSideNavService], (service: AuthorisedSideNavService) => {
    expect(service).toBeTruthy();
  }));
});


text:
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class AuthorisedSideNavService {
  hideSideNav: boolean = false;

  constructor() { }

  toggleSideNav(): void {
    this.hideSideNav = !this.hideSideNav;
  }
}


text:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { AuthorisedTopNavComponent } from './authorised-top-nav.component';
import { Component } from '@angular/core';

@Component({selector: 'app-authorised-side-nav-toggler', template: ''})
class AuthorisedSideNavTogglerComponent {}

describe('AuthorisedTopNavComponent', () => {
  let component: AuthorisedTopNavComponent;
  let fixture: ComponentFixture<AuthorisedTopNavComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        AuthorisedTopNavComponent,
        AuthorisedSideNavTogglerComponent
       ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AuthorisedTopNavComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});


text:
  <app-authorised-side-nav-toggler></app-authorised-side-nav-toggler>

keep_growing


text:
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-authorised-top-nav',
  templateUrl: './authorised-top-nav.component.html',
  styleUrls: ['./authorised-top-nav.component.scss']
})
export class AuthorisedTopNavComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}


text:
h3 {
  color: orange;
}


text:
<button  type="button" class="navbar-toggler" (click)="sideNavService.toggleSideNav()">

</button>


text:
import { Component, OnInit } from '@angular/core';

import { AuthorisedSideNavService } from '../services/authorised-side-nav.service';

@Component({
  selector: 'app-authorised-side-nav-toggler',
  templateUrl: './authorised-side-nav-toggler.component.html',
  styleUrls: ['./authorised-side-nav-toggler.component.scss']
})
export class AuthorisedSideNavTogglerComponent implements OnInit {

  constructor(public sideNavService: AuthorisedSideNavService) { }

  ngOnInit() {
  }

}


text:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { AuthorisedSideNavTogglerComponent } from './authorised-side-nav-toggler.component';

describe('AuthorisedSideNavTogglerComponent', () => {
  let component: AuthorisedSideNavTogglerComponent;
  let fixture: ComponentFixture<AuthorisedSideNavTogglerComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ AuthorisedSideNavTogglerComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AuthorisedSideNavTogglerComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});


text:
:host {
  background: #343a40;
}

#sidebar {
min-width: 200px;
max-width: 200px;
min-height: 100vh;
color: #fff;
transition: all 0.3s;
font-weight: 300;
font-size: 1rem;
line-height: 1.5;
}

#sidebar.hidden {
  margin-left: -200px;
}

a[data-toggle="collapse"] {
  position: relative;
}

@media (max-width: 575px) {
  #sidebar {
      margin-left: -200px;
  }
  #sidebar.hidden {
      margin-left: 0;
  }
}

a, a:hover, a:focus {
  color: inherit;
}

#sidebar .sidebar-header {
  padding: 20px;
}

#sidebar ul li a {
padding: 15px;
display: block;
width: 100%;
&:hover {
  background-color: rgba(255, 255, 255, 0.1);
}
}

hr {
border-top: 1px solid #fff;
margin-top: 0;
}


text:
      Home page

      Link

      Link


text:
import { Component, OnInit } from '@angular/core';
import { AuthorisedSideNavService } from '../services/authorised-side-nav.service';

@Component({
  selector: 'app-authorised-side-nav',
  templateUrl: './authorised-side-nav.component.html',
  styleUrls: ['./authorised-side-nav.component.scss']
})
export class AuthorisedSideNavComponent implements OnInit {

  constructor(public sideNavService: AuthorisedSideNavService) { }

  ngOnInit() {
  }

}


text:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { AuthorisedSideNavComponent } from './authorised-side-nav.component';

describe('AuthorisedSideNavComponent', () => {
  let component: AuthorisedSideNavComponent;
  let fixture: ComponentFixture<AuthorisedSideNavComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ AuthorisedSideNavComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AuthorisedSideNavComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
  it('should render menu in the top navigation', async(() => {
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('nav').textContent).toContain('LinkLink');
  }));
});


text:
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-guest-layout',
  templateUrl: './guest-layout.component.html',
  styleUrls: ['./guest-layout.component.scss']
})
export class GuestLayoutComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}


text:
  <app-guest-top-nav></app-guest-top-nav>
  <app-page-content></app-page-content>
  <app-guest-footer></app-guest-footer>


text:
.wrapper {
  display: flex;
  flex-direction: column;
  height: 100%;
  justify-content: space-between;
}


text:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { GuestLayoutComponent } from './guest-layout.component';

import { Component } from '@angular/core';

@Component({selector: 'app-guest-top-nav', template: ''})
class GuestTopNavComponent {}

@Component({selector: 'app-page-content', template: ''})
class PageContentComponent { }

@Component({selector: 'app-guest-footer', template: ''})
class GuestFooterComponent {}

describe('GuestLayoutComponent', () => {
  let component: GuestLayoutComponent;
  let fixture: ComponentFixture<GuestLayoutComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        GuestLayoutComponent,
        GuestTopNavComponent,
        PageContentComponent,
        GuestFooterComponent
       ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(GuestLayoutComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});