Maximilian
Maximilian

Reputation: 537

Calculate current time in percentage in relation to sunrise and sunset time?

I think what I would like to achieve can best be described with the graph I've made below:

Day Night Cycle In Percentage

I'm getting my sunrise and sunset data from an API that returns an object like this:

{
  sunrise: "07:58:38",
  sunset: "15:52:46",
  day_length: "07:54:08",
}

I'm currently calculating whether it's currently day or night time with this if statement:

const date = moment().format("YYYY-MM-DD")

let dayOrNight = "Day"

if (moment().isAfter(`${date} ${location.sunrise}`) && moment().isBefore(`${date} ${location.sunset}`)) {
  dayOrNight = "Day"
} else {
  dayOrNight = "Night"
}

All I need is a percentage value based on the current time in relation to this sunrise and sunset data.

For example, if this is my dataset:

{
  sunrise: "00:00:00",
  sunset: "10:00:00",
}

and my current time is perfectly between of both sunrise and sunset times which in this case would be 05:00:00 or 17:00:00, then my current time would equate to 100%. 02:30:00, 07:30:00 would equate to 50%.

Upvotes: 1

Views: 436

Answers (1)

spc
spc

Reputation: 447

Hi,

Solution

I think it would be logical to work with seconds.

  • Find the day midpoint and night midpoint times. (day_midpoint_in_sec + 12 x 60 x 60 seconds will be night midpoint)
  • Find percent_per_second for day and night (for day => (day_midpoint_in_sec - sunrise_in_sec) / 100 )
  • Find if given_time is day/night. (you have already solved it)
  • if it's day time then set elapsed_sec = given_time_in_sec - sunrise_in_sec
  • if given_time > day_midpoint, percentage is 200 - (elapsed_sec x percent_per_second)
  • else percentage is elapsed_sec x percent_per_second

Similarly you can easily work out for night time.

OR

On second thought,and on inspection of the graph,

  • Find everything relative to sunrise. ( day_midpoint_in_sec , night_midpoint_in_sec and sunset)
  • Apply equations depending upon where given_time_in_sec lies (good old y = mx + c) to get the percentages

We will get 4 equations:-

y = (100x)/day_midpoint_in_sec
y = (-100x/(sunset_in_sec - day_midpoint_in_sec)) + 100
y = 100x/(night_midpoint_in_sec - sunset)
y = (-100x/(24*60*60 - sunset_in_sec) - sunset_in_sec) + 100

Edit

Hi, as the second solution has become more complicated (also i have noticed some edge cases and mistake from my part), i have made a working snippet based on first solution.


let api = {
  sunrise: "00:00:00",
  sunset: "10:00:00",
};


const date = moment().format("YYYY-MM-DD")

let sunrise = moment(`${date} ${api.sunrise}`);
let sunset = moment(`${date} ${api.sunset}`);
let hour_24 = moment(`${date} 24:00:00`);
let hour_0 = moment(`${date} 00:00:00`);

let sunset_till_hour24 = hour_24.clone().subtract(sunset);
let hour24_till_sunrise = sunrise.clone().subtract(hour_0);

let midnight = sunset.clone().add(sunset_till_hour24.clone().add(hour24_till_sunrise).valueOf()/2);
let midday = sunrise.clone().add(sunset.clone().subtract(sunrise).valueOf()/2);



let givenTime = "17:10:00";
let given_time = moment(`${date} ${givenTime}`);


function findTimePercent(time, sunrise, midday, sunset, midnight) {
  let day_percent_per_ms = 100/midday.clone().subtract(sunrise).valueOf();
  let night_percent_per_ms = 100/midnight.clone().subtract(sunset).valueOf();
 

  let percent = 0;

  if (time.isSame(sunrise) || time.isSame(sunset)) {
    return 0;
  } else if (time.isSame(midday) || time.isSame(midnight)) {
    return 100;
  }
  
  // isBetween is exclusive
  if (time.isBetween(sunrise, midday)) {
      percent = time.subtract(sunrise).valueOf() * day_percent_per_ms;
  } else if(time.isBetween(midday, sunset)) {
      percent = 100 - (time.subtract(midday).valueOf() * day_percent_per_ms);
  } else if(time.isBetween(sunset, midnight)) {
      percent = time.subtract(sunset).valueOf() * night_percent_per_ms;
  } else {
      percent = 100 - (time.subtract(midnight).valueOf() * night_percent_per_ms);
  }
  
  return percent;

}


console.log(findTimePercent(given_time, sunrise, midday, sunset, midnight));

I hope this is self explanatory.

Upvotes: 1

Related Questions