🎉 Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io 🎉
Avatar of bathrobe

bathrobe's solution

to Gigasecond in the Elixir Track

Published at Mar 29 2021 · 0 comments
Instructions
Test suite
Solution

Calculate the moment when someone has lived for 10^9 seconds.

A gigasecond is 10^9 (1,000,000,000) seconds.

Running tests

Execute the tests with:

$ mix test

Pending tests

In the test suites, all but the first test have been skipped.

Once you get a test passing, you can unskip the next one by commenting out the relevant @tag :pending with a # symbol.

For example:

# @tag :pending
test "shouting" do
  assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
end

Or, you can enable all the tests by commenting out the ExUnit.configure line in the test suite.

# ExUnit.configure exclude: :pending, trace: true

If you're stuck on something, it may help to look at some of the available resources out there where answers might be found.

Source

Chapter 9 in Chris Pine's online Learn to Program tutorial. http://pine.fm/LearnToProgram/?Chapter=09

Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

gigasecond_test.exs

defmodule GigasecondTest do
  use ExUnit.Case

  # @tag :pending
  test "from 4/25/2011" do
    assert Gigasecond.from({{2011, 4, 25}, {0, 0, 0}}) == {{2043, 1, 1}, {1, 46, 40}}
  end

  @tag :pending
  test "from 6/13/1977" do
    assert Gigasecond.from({{1977, 6, 13}, {0, 0, 0}}) == {{2009, 2, 19}, {1, 46, 40}}
  end

  @tag :pending
  test "from 7/19/1959" do
    assert Gigasecond.from({{1959, 7, 19}, {0, 0, 0}}) == {{1991, 3, 27}, {1, 46, 40}}
  end

  @tag :pending
  test "yourself" do
    # customize these values for yourself
    # your_birthday = {{year1, month1, day1}, {0, 0, 0}}
    # assert Gigasecond.from(your_birthday) == {{year2, month2, day2}, {hours, minutes, seconds}}
  end
end

test_helper.exs

ExUnit.start()
ExUnit.configure(exclude: :pending, trace: true)
defmodule Gigasecond do
  @doc """
  Calculate a date one billion seconds after an input date.
  """
  @spec from({{pos_integer, pos_integer, pos_integer}, {pos_integer, pos_integer, pos_integer}}) ::
          :calendar.datetime()

  def from({{year, month, day}, {hours, minutes, seconds}}) do
  # piecing the incoming tuples together to get a DateTime object
  gd = elem(Date.new(year,month,day), 1)
  gt = elem(Time.new(hours,minutes,seconds),1)
  gdt = elem(DateTime.new(gd,gt),1)
  # using the DateTime add method
  gigatime = DateTime.add(gdt, 1000000000)
  # formatting the gigatime into tuple pair
  {{gigatime.year, gigatime.month, gigatime.day}, {gigatime.hour, gigatime.minute, gigatime.second}}
  end
end

Community comments

Find this solution interesting? Ask the author a question to learn more.

bathrobe's Reflection

I started this challenge by trying to manually convert a billion seconds into the formatted tuple pair, then adding the raw numbers to the parameters of the function. It wasn't long before I realized there was no smart way to factor in the variance in days per month. (A gigasecond is 11,574 days, FYI).
Then I searched and found Elixir's inbuilt Date methods, which contained an add function. Since the incoming times were `{{pairs of}, {tuples}}` I needed to piece them together to create a DateTime object.
Once I got that done, I was pleasantly surprised to find that all I needed to do was `.add(formattedTime, one billion seconds)`.