# pregnancy

    library(pregnancy)

This is an R package for calculating dates and tracking medications during pregnancy and fertility treatment. It extends a private, personal package that I wrote for myself when I was pregnant. It contains functions and features that I found useful at the time, and others that I added when adapting the package for general use.

The functionality goes beyond what’s offered by online pregnancy calculators and apps, plus there are no concerns (unlike with these sites and apps) about data privacy, tracking or advertising.

## A note on dates

To easily keep this vignette fairly up-to-date, and prevent recurring package build and CRAN failures as time goes by, I have not hard-coded any dates here. Instead, I have calculated everything from the date on which this vignette built. That was on January 13, 2026, so for the purposes of reading this page, that counts as “today”.

The pregnancy package uses dates extensively. Any function argument that requires a date can either take a `Date` object1, or a character string that can be parsed to a `Date`, e.g. `"YYYY-MM-DD"`. The parsing is performed by `anytime::anydate()`.

## Date calculations

The `calculate_due_date()` function estimates the pregnancy due date. The `start_date` is interpreted differently, depending on the `start_type`. By default, the `start_type` is the last menstrual period, and the `start_date` is the date this started. Other `start_date` options, like various transfer days, are useful for those using IVF.

    # for purpose of vignette, calculate `start_date` relative to "today"
    today <- Sys.Date()
    start_date <- today - 192

    # invisibly returns a Date object with the estimated due date
    # by default, start date of last menstrual period, but other options available
    # in practice, the start_date argument will be a known date, e.g. "2025-05-29"
    due_date <- calculate_due_date(start_date)
    #> ℹ Estimated due date: Saturday, April 11, 2026
    #> ℹ Estimated birth period begins: March 21, 2026 (37 weeks)
    #> ℹ Estimated birth period ends: April 25, 2026 (42 weeks)

Once a due date is know, `how_far()` tells you how far along the pregnancy is on a given date. It defaults to providing this information for the current date, but an alternative `on_date` can be provided. See the section below on global options for how to avoid needing to pass in the `due_date` value every time you call these function.

    how_far(due_date = due_date)
    #> ℹ You are 27 weeks and 3 days pregnant.
    #> ℹ That's 12 weeks and 4 days until the due date (April 11, 2026).
    #> ℹ You are 69% through the pregnancy.
    how_far(on_date = today + 1, due_date = due_date)
    #> ℹ On January 14, 2026, you will be 27 weeks and 4 days pregnant.

The `date_when()` function gives the date when a certain week of pregnancy will be (or was) reached, and the duration of that date from today:

    date_when(33, due_date = due_date)
    #> ℹ On February 21, 2026, you will be 33 weeks pregnant.
    #> ℹ That's 5 weeks and 4 days away.

By default, the output messages from `how_far()` and `date_when()` are in the second person, i.e. addressed to “you”, but there is also an option to specify another person. A value of `1` or `"I"` means you’ll be addressed in the first person:

    how_far(due_date = due_date, person = 1)
    #> ℹ I am 27 weeks and 3 days pregnant.
    #> ℹ That's 12 weeks and 4 days until the due date (April 11, 2026).
    #> ℹ I am 69% through the pregnancy.

Any other character string will be interpreted as a third-person name, which is useful, for example, if you’re following the pregnancy progress of a partner:

    date_when(33, due_date = due_date, person = "Ruth")
    #> ℹ On February 21, 2026, Ruth will be 33 weeks pregnant.
    #> ℹ That's 5 weeks and 4 days away.

There is one further date-related function in the package, which is useful if you are not yet pregnant but think there’s a chance you might be, e.g. if you are undergoing fertility treatment. This is `calculate_test_date()`, which calculates the recommended date for taking a pregnancy test, based on start date (e.g. start of last menstural period) and test type:

    calculate_test_date(today - 20)
    #> ℹ Estimated test date (urine): Wednesday, January 21, 2026
    #> ℹ Estimated test date (blood): Monday, January 19, 2026

## Tracking medications

For those who get pregnant via fertility treatment, it is likely they need to take a number of different medications to support the pregnancy. Having functionality for tracking these is useful for both practical and emotional reasons. When I was pregnant, in my personal, private pregnancy package, whenever I called my version of `how_far`, it would print a message with how many injections I had already endured, and how many I had left to go, which helped me get through them.

I haven’t written that functionality into `how_far()` in this generalised version of the pregnancy package, but I have provided a separate `medications_remaining()` function to keep track of medications. It requires a data frame of medications, which must have the following columns with the specified data types:

Column name | Data type | Description
--- | --- | ---
medication | character or factor | name of the medication
format | character or factor | format of the medication (e.g. pill, injection)
quantity | numeric | number of units to take per day
start_date | Date or string representing a date, e.g. “YYYY-MM-DD” | date to start taking the medication
stop_date | Date or string representing a date, e.g. “YYYY-MM-DD” | final date on which medication is taken

Note that if the quantity of a given medication changes during the pregnancy, you need separate rows with the start and stop dates for each quantity.

Here’s an example of what a simple `medications` table might look like:

    # a simplified medication schedule
    meds <- pregnancy:::update_meds_table(pregnancy::medications_simple)
    meds
    #> # A tibble: 4 × 5
    #>   medication format    quantity start_date stop_date
    #>   <chr>      <chr>        <dbl> <date>     <date>
    #> 1 progynova  tablet           3 2025-12-30 2026-01-09
    #> 2 progynova  tablet           6 2026-01-10 2026-01-20
    #> 3 cyclogest  pessary          2 2026-01-12 2026-01-20
    #> 4 clexane    injection        1 2026-01-17 2026-03-16

You can then calculate the quantity of medications left to take grouped by either by medication (default) or format. By default, the calculation is for today (i.e. `on_date` = `Sys.Date()`). The resulting table assumes that the function is being called first thing in the day, i.e. before any of `on_date`’s medications have been taken.

    medications_remaining(meds)
    #> # A tibble: 3 × 2
    #>   medication quantity
    #>   <chr>         <int>
    #> 1 clexane          59
    #> 2 cyclogest        16
    #> 3 progynova        48

    medications_remaining(meds, group = "format")
    #> # A tibble: 3 × 2
    #>   format    quantity
    #>   <chr>        <int>
    #> 1 injection       59
    #> 2 pessary         16
    #> 3 tablet          48

You can specify a value other than today for `on_date`, as well as an `until_date`. This is useful if you need (as I did) to order a couple of week’s medication at the time, and have to tell the pharmacy exactly what you need:

    medications_remaining(
      meds,
      on_date = today + 3,
      until_date = today + 17
    )
    #> # A tibble: 3 × 2
    #>   medication quantity
    #>   <chr>         <int>
    #> 1 clexane          14
    #> 2 cyclogest        10
    #> 3 progynova        30

## Global options

It would be very tedious to have to enter a due date every time you call `how_far()` or `date_when()` over the course of a pregnancy, especially since that date is constant throughout. The same goes for the medications table required for `medications_remaining()`.

To avoid this, the pregnancy package makes use of global options, which can be set with the `set_*` family of functions (`set_due_date()`, `set_person()`, `set_medications()`). These functions only set the options for the current R session.

To ensure the options persist across all R sessions, we suggest setting them in your `.Rprofile`, and give an example at the end of this vignette.

Global options can be retrieved with the `get_*` family of functions (`get_due_date()`, `get_person()`, `get_medications()`).

Any global option can be unset by calling its `set_*` function with the argument `NULL`.

### `pregnancy.due_date`

You can set the `pregnancy.due_date` option using the `set_due_date()` function.

When that option is set, if the `due_date` argument to `how_far()` or `date_when()` is `NULL` (the default), that option is retrieved.

`set_due_date()` only sets the due date for the current R session. To make this option persist (recommended), it can be added to your `.Rprofile`. The console output of `set_due_date()` provides guidance on how to do this.

    # a different due date from the earlier example
    due_date <- today + 180
    set_due_date(due_date)
    #> ✔ Due date set as July 12, 2026
    #> ℹ Functions in the pregnancy package will now use this `due_date` option.
    #> ℹ So, for this R session, you do not need to supply a value to the `due_date`
    #>   argument (unless you wish to override the option).
    #> ℹ To make this `due_date` option available in all R sessions, in your
    #>   ".Rprofile", set `options(pregnancy.due_date = ...)`
    #>   where ... is the value of `due_date`.
    #> ℹ You can edit your ".Rprofile" by calling `usethis::edit_r_profile()`
    #> ℹ You can retrieve the `due_date` option with `get_due_date()`,
    #>   or with `getOption('pregnancy.due_date')`.

Then `how_far()` can be called without needing to specify any arguments, and `date_when()` only needs the target week:

    how_far()
    #> ℹ You are 14 weeks and 2 days pregnant.
    #> ℹ That's 25 weeks and 5 days until the due date (July 12, 2026).
    #> ℹ You are 36% through the pregnancy.

    date_when(20)
    #> ℹ On February 22, 2026, you will be 20 weeks pregnant.
    #> ℹ That's 5 weeks and 5 days away.

To check what the option is set to, use `get_due_date()`.

### `pregnancy.person`

`set_person()` sets the global option `pregnancy.person` for the current R session. If this option is set it will be retrieved to specify the value of `person` in `how_far()` and `date_when()`, unless it is overriden by passing another value directly to the `person` argument. If the option is not set, the default second-person will be used.

    set_person(1)
    #> ✔ person set as 'I'
    #> ℹ Functions in the pregnancy package will now use this `person` option.
    #> ℹ So, for this R session, you do not need to supply a value to the `person`
    #>   argument (unless you wish to override the option).
    #> ℹ To make this `person` option available in all R sessions, in your
    #>   ".Rprofile", set `options(pregnancy.person = ...)`
    #>   where ... is the value of `person`.
    #> ℹ You can edit your ".Rprofile" by calling `usethis::edit_r_profile()`
    #> ℹ You can retrieve the `person` option with `get_person()`,
    #>   or with `getOption('pregnancy.person')`.
    how_far() # due_date option still set from previous section
    #> ℹ I am 14 weeks and 2 days pregnant.
    #> ℹ That's 25 weeks and 5 days until the due date (July 12, 2026).
    #> ℹ I am 36% through the pregnancy.
    set_person(NULL)
    #> ✔ pregnancy.person option set to NULL.
    #> ℹ The `person` argument will now default to "You".
    how_far()
    #> ℹ You are 14 weeks and 2 days pregnant.
    #> ℹ That's 25 weeks and 5 days until the due date (July 12, 2026).
    #> ℹ You are 36% through the pregnancy.

### `pregnancy.medications`

`set_medications()` sets the global option `pregnancy.medications` for the current R session.

When that option is set, if the `meds` argument to `medications_remaining()` is `NULL` (the default), that option is retrieved.

    set_medications(pregnancy:::update_meds_table(pregnancy::medications))
    #> ✔ medications set.
    #> ℹ Functions in the pregnancy package will now use this `medications` option.
    #> ℹ So, for this R session, you do not need to supply a value to the
    #>   `medications` argument (unless you wish to override the option).
    #> ℹ To make this `medications` option available in all R sessions, in your
    #>   ".Rprofile", set `options(pregnancy.medications = ...)`
    #>   where ... is the value of `medications`.
    #> ℹ You can edit your ".Rprofile" by calling `usethis::edit_r_profile()`
    #> ℹ You can retrieve the `medications` option with `get_medications()`,
    #>   or with `getOption('pregnancy.medications')`.
    medications_remaining()
    #> # A tibble: 6 × 2
    #>   medication   quantity
    #>   <chr>           <int>
    #> 1 LDA                 4
    #> 2 clexane           120
    #> 3 cyclogest         138
    #> 4 lubion             69
    #> 5 prednisolone      289
    #> 6 progynova         414

### An example `.Rprofile`

Taking the advice to specify the options in your `.Rprofile`, here’s an example of what that might look like:

    options(
      pregnancy.due_date = "2025-09-16",
      pregnancy.person = "I", # addressed in first person
      pregnancy.medications = dplyr::tribble(
        ~medication, ~format, ~quantity, ~start_date, ~stop_date,
        "progynova", "tablet", 3, "2025-04-21", "2025-04-30",
        "progynova", "tablet", 6, "2025-05-01", "2025-07-11",
        "cyclogest", "pessary", 2, "2025-05-03", "2025-07-11",
        "clexane", "injection", 1, "2025-05-08", "2025-09-05"
      )
    )

Note that it is best to avoid creating R objects in your `.Rprofile`, e.g. a `medications` data frame outside of the call to `options()`, otherwise that object will be loaded into your global environment at the start of every R session.

1. There are many ways to create `Date` objects in R, including `as.Date()`, `lubridate::ymd()`, and `anytime::anydate()`.↩︎