Free Use Bible API
Руководство
Справочник
SDK
GitHub
Пожертвовать
  • English
  • Afrikaans
  • አማርኛ
  • العربية
  • বাংলা
  • Deutsch
  • Español
  • Français
  • Hausa
  • हिन्दी
  • Bahasa Indonesia
  • Italiano
  • 日本語
  • Português
  • Русский
  • Kiswahili
  • اردو
  • 简体中文
  • isiZulu
Руководство
Справочник
SDK
GitHub
Пожертвовать
  • English
  • Afrikaans
  • አማርኛ
  • العربية
  • বাংলা
  • Deutsch
  • Español
  • Français
  • Hausa
  • हिन्दी
  • Bahasa Indonesia
  • Italiano
  • 日本語
  • Português
  • Русский
  • Kiswahili
  • اردو
  • 简体中文
  • isiZulu
  • Справочник

    • API
    • Переводы, книги и главы
      • Стандартный формат
      • Упрощенный формат
    • Комментарии
    • Наборы данных
      • Конвенция «Стих дня»
    • OpenAPI

Конвенция «Стих дня»

На этой странице описано, как выбрать стих дня из набора данных verse-of-the-day , чтобы вы могли реализовать его на любом языке и получить тот же стих, что и в любой другой реализации.

API состоит из статических файлов, поэтому он не выбирает стих за вас. Используется общепринятая практика по умолчанию: приложения, которые её придерживаются, показывают один и тот же стих в один и тот же день. Приложения могут выбирать другие стихи, и начальное значение предоставляет им простой способ сделать это, сохраняя при этом те же гарантии.

Гарантии

  • Детерминированный процесс. Одна и та же дата (и начальное значение генератора случайных чисел) всегда выдает один и тот же стих на любом устройстве и при любой реализации.
  • В течение года нет повторов. Каждый год имеет свой собственный перемешанный порядок стихов, и дни года следуют этому порядку. В наборе данных всегда содержится не менее 366 стихов для каждого используемого дня, поэтому стих никогда не появляется дважды в одном и том же календарном году.
  • Праздники. В христианские праздники (например, Рождество или Воскресение Христово) стих дня — это один из стихов этого праздника. Стихи праздника читаются ежегодно, поэтому каждый год используется новый стих, пока не будут использованы все стихи. В праздники, которые длятся несколько дней (например, три дня после Воскресения Христова), каждый день используется новый стих. В другие дни стихи праздника не используются.
  • Каждый год порядок повторяется. После того, как все стихи использованы, порядок не повторяется. Поскольку каждый год перемешивается отдельно, один и тот же стих может иногда появляться 31 декабря и снова 1 января (примерно в 1 из 650 случаев на Новый год).
  • Стабильная история. В набор данных добавляются или удаляются стихи только из года, который еще не начался (см. addedIn и removedIn ), поэтому стих дня для даты, которая уже наступила, никогда не меняется.
  • Независимо от порядка в списке. Место каждого стиха в годовом порядке определяется его собственной ссылкой, поэтому порядок в списке не имеет значения.

Входные данные

ВходОписание
СтихиМассив verses из /api/d/verse-of-the-day/verses.json Каждый стих содержит book , chapter , verse и categories , а также может содержать endVerse , addedIn и removedIn .
ДатаКалендарная дата (год, месяц и день). Для поля «сегодня» используйте локальную дату пользователя, а не дату в формате UTC.
СемяНеобязательный параметр. Строка, указывающая на другой порядок. По умолчанию используется пустая строка, которая отображает стандартный стих дня.
ПраздникиМассив holidays из того же файла. Каждый праздник имеет значение id своей категории, а также либо month и day (праздник, отмечаемый в один и тот же день каждый год), либо список из dates ( YYYY-MM-DD , по порядку) для праздника, дата которого меняется каждый год. Праздник может включать несколько дат в одном году, если он длится несколько дней.
КатегорияНеобязательно. Выбирайте только те стихи, у которых эта категория находится в диапазоне categories , в любой день.

Алгоритм

Шаг 1: Найдите год и день года.

Возьмите год, месяц и день недели, а также день года, соответствующий этой дате, считая от 0: 1 января — это день 0, 31 декабря — это день 364 (или день 365 в високосном году).

В календаре используется пролептический григорианский календарь: год считается високосным, если он делится на 4, за исключением лет, делящихся на 100, но не делящихся на 400 (2000 год — високосный, 1900 — нет).

Шаг 2: Сохраните используемые стихи.

Сохраните стихи, которые используются в течение года:

  • addedIn отсутствует (или равно нулю), или addedIn <= year , и
  • removedIn отсутствует (или равно нулю), или year < removedIn .

Шаг 3: Выберите стихи, из которых хотите выбрать.

Выберите стихи для исполнения, ключевой префикс для шага 4 и позицию для шага 7:

  1. Была задана категория. Сохраняйте используемые стихи, в которых categories содержит эту категорию. Приставка — {seed}|{year} , а позиция — день года.
  2. Категория не указана, и дата является праздником. Дата считается праздником, если праздник в holidays содержит цифры month и day даты, или если дата указана в dates (записывается как YYYY-MM-DD , с четырехзначным годом). Если совпадает более одного праздника, используйте первый из списка (в наборе данных никогда не бывает двух праздников на одну и ту же дату). Сохраняйте используемые стихи, categories которых содержат цифру id праздника. Если такие стихи есть, префикс равен {seed}|{id} (например, |christmas ), а позиция — year × k + i , где k — количество дней, в течение которых праздник отмечается в году (1 для праздника с month и day ; в противном случае — количество его dates в году даты), а i — количество дней, предшествующих дате. Для праздника, который отмечается один день в году, позиция — это просто год. Если таких нет, продолжайте с 3.
  3. В противном случае. Сохраняйте используемые стихи, в которых categories не содержит id какого-либо праздника из holidays Префикс — {seed}|{year} , а позиция — день года.

seed — это начальное значение (по умолчанию пустая строка), а year — это год из шага 1 в десятичном формате без ведущих нулей (например 2026 , 1 ).

Если не осталось ни одного стиха, то нет и стиха дня.

В списке праздников, даты которых меняются каждый год, указаны только предварительно рассчитанные даты (в настоящее время с 2026 по 2125 год), поэтому в другие годы это обычные дни. Не рассчитывайте даты самостоятельно.

Шаг 4: Составьте ключевой тон каждого куплета.

Для каждого оставшегося куплета сформируйте следующую строку:

{prefix}|{book} {chapter}:{verse}
  • prefix — это префикс из шага 3.
  • book — это book цифра стиха, точно так, как она указана в наборе данных (заглавная буква идентификатора книги USFM, например, JHN или 1JN ).
  • chapter и verse — это десятичные числа без ведущих нулей.
  • endVerse не является частью ключа. Отрывок определяется по его первому стиху.

Например, ключ для Иоанна 3:16 в обычный день 2026 года при использовании начального значения генератора случайных чисел равен |2026|JHN 3:16 , а ключ для Луки 2:7 на Рождество равен |christmas|LUK 2:7 .

Шаг 5: Хэшируйте каждый ключ.

Хэшируйте байты ключа в формате UTF-8 с помощью 32-битного хеша FNV-1a , затем смешайте результат с финализатором MurmurHash3 fmix32 Все арифметические операции выполняются над беззнаковыми 32-битными целыми числами, поэтому умножения циклически повторяются (они берутся по модулю 2³²), а сдвиги вправо являются логическими (они сдвигаются на нули).

hash = 0x811C9DC5
for each byte b in UTF-8(key):
    hash = hash XOR b
    hash = (hash * 0x01000193) mod 2^32

hash = hash XOR (hash >> 16)
hash = (hash * 0x85EBCA6B) mod 2^32
hash = hash XOR (hash >> 13)
hash = (hash * 0xC2B2AE35) mod 2^32
hash = hash XOR (hash >> 16)

В результате получается ключ сортировки стиха — число от 0 до 4 294 967 295.

Шаг 6: Распределите стихи по местам.

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

Если у двух стихов одинаковый ключ сортировки (что встречается крайне редко), то в порядковом порядке (по коду символа) первым следует тот стих, ключевая строка которого из шага 4 стоит первой. Все ключевые строки начинаются с одного и того же префикса, поэтому они различаются только последующей ASCII-ссылкой.

Шаг 7: Выберите стих

Стих дня — это стих, занимающий позицию p mod n в отсортированном списке (считая с 0), где p — это позиция из шага 3 (день года или year × k + i в праздничный день), а n — количество стихов в отсортированном списке. Результат mod никогда не бывает отрицательным (для отрицательного года добавляйте n , пока он не станет отрицательным).

В обычные дни полный набор данных содержит как минимум 366 стихов, поэтому day mod n равно day Цифра mod имеет значение, когда вы выбираете из категории или собственного списка, в котором меньше стихов, чем дней в году, в этом случае стихи повторяются в течение года. В праздничные дни позиция проходит по стихам праздника за один год (а для праздника, длящегося несколько дней, за один день).

Псевдокод

function verseOfTheDay(verses, holidays, date, seed = "", category = null):
    year = date.year
    day = dayOfYear(date)                 // 0 for January 1st
    inUse = [v for v in verses
             if (v.addedIn == null or v.addedIn <= year)
             and (v.removedIn == null or year < v.removedIn)]

    if category != null:
        return pick([v for v in inUse if category in v.categories], seed + "|" + year, day)

    holiday = first h in holidays where (h.month == date.month and h.day == date.day)
                                     or (h.dates contains format(date, "YYYY-MM-DD"))
    if holiday != null:
        holidayVerses = [v for v in inUse if holiday.id in v.categories]
        if holidayVerses is not empty:
            if holiday.dates == null:
                position = year
            else:
                datesInYear = [d for d in holiday.dates if d starts with year + "-"]
                position = year * length(datesInYear) + count of d in datesInYear where d < date
            return pick(holidayVerses, seed + "|" + holiday.id, position)

    holidayIds = [h.id for h in holidays]
    return pick([v for v in inUse if no category of v is in holidayIds], seed + "|" + year, day)

function pick(candidates, prefix, position):
    if candidates is empty: return null
    keyed = [(hash(key), key, v) for v in candidates
             where key = prefix + "|" + v.book + " " + v.chapter + ":" + v.verse]
    sort keyed by (hash, key)             // hash as an unsigned number, key in ordinal order
    return keyed[position mod length(keyed)].verse    // a mod that is never negative

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

Семена

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

Распространенные ошибки

  • Знаковые целые числа. В языках, где нет беззнаковых 32-битных целых чисел (Java, Kotlin, JavaScript), арифметические операции выполняются над знаковыми 32-битными целыми числами с использованием логического сдвига вправо ( >>> ), затем результат преобразуется в беззнаковое значение (например, hash.toLong() and 0xFFFFFFFF или hash >>> 0 в JavaScript) перед сравнением. В JavaScript для умножения используется Math.imul ; * приводит к потере точности.
  • Хэширование символов вместо байтов. Хэшируются байты UTF-8 ключа, а не его кодовые единицы UTF-16 или кодовые точки Unicode. Это имеет значение только для начальных значений, содержащих не-ASCII символы, но они допускаются.
  • Для обозначения "сегодня" используется UTC. Стих дня меняется в полночь по местному времени пользователя. Использование даты в формате UTC показывает стих предыдущего или следующего дня для части дня в большинстве часовых поясов.
  • Отсчитывая день года от 1, 1 января считается нулевым днем.
  • Расчет дат праздников. Используйте значение dates указанное в наборе данных. Разные церкви и календари рассчитывают Пасху по-разному, и в наборе данных указаны только предварительно рассчитанные даты.
  • Если не учитывать праздники. Без holidays стихи о праздниках рассматриваются как обычные стихи, что меняет и стихи для каждого обычного дня.
  • Удалённые стихи исключены. Стихи с removedIn годом остаются в наборе данных, поскольку они необходимы для более ранних лет. Отфильтруйте их на шаге 2; не удаляйте их при загрузке списка.

Тестовые векторы

Используйте эти значения для проверки реализации.

Хэши

Ключ (в виде строки JSON)Ключ сортировкиШестиугольник
""28729989230xab3e7c0b
"a"4446417150x1a80b1b3
"|2026|JHN 3:16"19301904520x730c5e74
"my-app|2026|PSA 23:1"20201688430x7869548b
"é|1|GEN 1:1"36770646160xdb2b8da8

Дни года

ДатаГодДень года
2026-01-0120260
2026-12-312026364
2028-02-29202859
2028-12-312028365
1900-12-311900364
2000-12-312000365
0001-03-01159
9999-12-319999364

Выбор из небольшого списка

В них используется следующий список из шестнадцати стихов, восемь из которых посвящены праздникам:

[
    { "book": "GEN", "chapter": 1, "verse": 1, "categories": ["praise"] },
    {
        "book": "PSA",
        "chapter": 23,
        "verse": 1,
        "categories": ["comfort", "provision"]
    },
    {
        "book": "PRO",
        "chapter": 3,
        "verse": 5,
        "endVerse": 6,
        "categories": ["faith", "guidance"]
    },
    {
        "book": "ISA",
        "chapter": 40,
        "verse": 31,
        "categories": ["strength", "hope"]
    },
    {
        "book": "JHN",
        "chapter": 3,
        "verse": 16,
        "categories": ["love", "salvation"]
    },
    {
        "book": "ROM",
        "chapter": 8,
        "verse": 28,
        "categories": ["hope"],
        "removedIn": 2027
    },
    { "book": "PHP", "chapter": 4, "verse": 13, "categories": ["strength"] },
    {
        "book": "1JN",
        "chapter": 4,
        "verse": 19,
        "categories": ["love"],
        "addedIn": 2027
    },
    { "book": "LUK", "chapter": 2, "verse": 7, "categories": ["christmas"] },
    {
        "book": "LUK",
        "chapter": 2,
        "verse": 10,
        "endVerse": 11,
        "categories": ["christmas"]
    },
    {
        "book": "MAT",
        "chapter": 1,
        "verse": 23,
        "categories": ["christmas"],
        "addedIn": 2027
    },
    {
        "book": "MAT",
        "chapter": 28,
        "verse": 6,
        "categories": ["resurrection-sunday"]
    },
    {
        "book": "ACT",
        "chapter": 2,
        "verse": 24,
        "categories": ["post-resurrection-sunday"]
    },
    {
        "book": "ROM",
        "chapter": 6,
        "verse": 9,
        "categories": ["post-resurrection-sunday"]
    },
    {
        "book": "1CO",
        "chapter": 15,
        "verse": 20,
        "categories": ["post-resurrection-sunday"]
    },
    {
        "book": "1TH",
        "chapter": 4,
        "verse": 14,
        "categories": ["post-resurrection-sunday"]
    }
]

И вот эти праздники (в Сочельник нет стихов, поэтому это обычный день):

[
    { "id": "christmas-eve", "month": 12, "day": 24 },
    { "id": "christmas", "month": 12, "day": 25 },
    { "id": "resurrection-sunday", "dates": ["2026-04-05", "2027-03-28"] },
    {
        "id": "post-resurrection-sunday",
        "dates": [
            "2026-04-06",
            "2026-04-07",
            "2026-04-08",
            "2027-03-29",
            "2027-03-30",
            "2027-03-31"
        ]
    }
]

Для 1 января 2026 года при использовании стандартного начального значения четыре праздничных стиха и 1 Иоанна 4:19 (который пока не используется) исключены, поэтому осталось семь стихов. Отсортированные по ключам сортировки, они выглядят следующим образом:

ПозицияКлючКлюч сортировки
0|2026|PSA 23:1638659039
1|2026|ROM 8:281462075190
2|2026|PRO 3:51643805236
3|2026|JHN 3:161930190452
4|2026|PHP 4:132076082788
5|2026|GEN 1:12439817197
6|2026|ISA 40:313044461366

1 января — нулевой день, поэтому стих дня — Псалом 23:1. 15 марта — 73-й день, а 73 по модулю 7 = 3, поэтому это Иоанна 3:16.

На Рождество остаются только те рождественские стихи, которые используются в настоящее время. В 2027 году их три, отсортированные по ключам сортировки:

ПозицияКлючКлюч сортировки
0|christmas|LUK 2:101698480150
1|christmas|MAT 1:232563849700
2|christmas|LUK 2:73160581874

2027 mod 3 = 2, поэтому стих дня на Рождество 2027 года — это Лука 2:7. В 2026 году Матфей 1:23 еще не используется, поэтому их всего два, и 2026 mod 2 = 0 дает Лука 2:10-11.

Праздник после Воскресения Христова длится три дня. Четыре стиха, отсортированные по ключам, следующие:

ПозицияКлючКлюч сортировки
0|post-resurrection-sunday|1TH 4:1480824114
1|post-resurrection-sunday|ROM 6:9665551464
2|post-resurrection-sunday|1CO 15:20820536316
3|post-resurrection-sunday|ACT 2:243132510482

В 2026 году это событие отмечается в течение трёх дней, поэтому k = 3, и позиции 6, 7 и 8 апреля составляют 2026 × 3 + 0 = 6078, 6079 и 6080. 6078 mod 4 = 2, 6079 mod 4 = 3 и 6080 mod 4 = 0 дают 1 Коринфянам 15:20, Деяния 2:24 и 1 Фессалоникийцам 4:14. В 2027 году позиции продолжаются с 6081, поэтому следующий стих — Римлянам 6:9.

ДатаСемяКатегорияСтих дня
2026-01-01ПСА 23:1
2026-01-02Римлянам 8:28
2026-03-15Иоанн 3:16
2026-12-31ПСА 23:1
2027-01-01Иоанн 3:16
2027-06-30ПРО 3:5-6
2028-02-29ПРО 3:5-6
2028-12-31ПСА 23:1
1969-12-31ПРО 3:5-6
0001-01-01Исаия 40:31
2026-01-01my-appИсаия 40:31
2027-01-01my-appPHP 4:13
2026-01-01hopeРимлянам 8:28
2027-01-01hopeИсаия 40:31
2027-01-01joyНет стиха дня
2026-12-25ЛК 2:10-11
2027-12-25ЛК 2:7
2028-12-25ЛК 2:10-11
2029-12-25Мф 1:23
2026-12-25my-appЛК 2:10-11
2026-04-05Мф 28:6
2027-03-28Мф 28:6
2028-04-16ПСА 23:1
2026-12-24ПСА 23:1
2026-07-01christmasЛК 2:7
2026-04-061CO 15:20
2026-04-07Деяния 2:24
2026-04-081-е 4:14
2026-04-09ПСА 23:1
2027-03-29Римлянам 6:9
2027-03-301CO 15:20
2027-03-31Деяния 2:24

16 апреля 2028 года — Воскресение Христово, но оно не входит в этот список под номером dates , поэтому это обычный день.

Выбранные фрагменты из набора данных

В наборе данных стихи прошедшего года никогда не меняются, поэтому стихи 2026 года остаются неизменными:

ДатаПраздничный деньСтих дня
2026-01-01ПСА 32:1
2026-04-03Страстная пятницаЛк 23:33
2026-04-05Воскресение ХристовоМф 28:9
2026-04-06После Воскресения ХристоваОткр 1:17-18
2026-06-15EST 4:14
2026-10-28ПСА 136:1
2026-10-31Канун Дня всех святыхЕФ 5:8
2026-11-29Первое воскресенье АдвентаМАЛ 3:1
2026-12-24сочельникМф 1:21
2026-12-25РождествоИсаия 9:6
2026-12-31Иезек. 36:26

Реализации

Эти реализации следуют общепринятой конвенции, и их тесты проверяют значения, указанные на этой странице:

  • JavaScript/TypeScript: pickVerseOfTheDay() и FreeUseBibleApi.getVerseOfTheDay() в пакете free-use-bible-api ( источник ).
  • Kotlin: pickVerseOfTheDay() и FreeUseBibleApi.getVerseOfTheDay() в Kotlin SDK ( исходный код ).
  • Swift: pickVerseOfTheDay(_:date:seed:category:holidays:) и FreeUseBibleAPI.getVerseOfTheDay(date:seed:category:dataset:endpoint:) в Swift SDK ( исходный код ).
  • getVerseOfTheDay инструмент сервера MCP ( источник ).
  • getVerseOfTheDay() из @helloao/tools ( источник ), который использует список, встроенный в пакет.