Javascript or Python - How do I figure out if it's night or day?

前端 未结 3 742
感情败类
感情败类 2021-02-05 05:54

any idea how I figure out if it\'s currently night/day or sunrise/dawn based on time and location of the user?

I haven\'t found anything useful that I c

相关标签:
3条回答
  • 2021-02-05 06:41

    PyEphem can be used to calculate the time to the next sunrise and sunset. Building upon a blog post I found and the documentation of rise-set, your problem can be solved as follows. Lets assume I am your user, and my location is Oldenburg (Oldb), Germany.

    import ephem
    
    user = ephem.Observer()
    user.lat = '53.143889'    # See wikipedia.org/Oldenburg
    user.lon = '8.213889'     # See wikipedia.org/Oldenburg
    user.elevation = 4        # See wikipedia.org/Oldenburg
    user.temp = 20            # current air temperature gathered manually
    user.pressure = 1019.5    # current air pressure gathered manually
    
    next_sunrise_datetime = user.next_rising(ephem.Sun()).datetime()
    next_sunset_datetime = user.next_setting(ephem.Sun()).datetime()
    
    # If it is daytime, we will see a sunset sooner than a sunrise.
    it_is_day = next_sunset_datetime < next_sunrise_datetime
    print("It's day." if it_is_day else "It's night.")
    
    # If it is nighttime, we will see a sunrise sooner than a sunset.
    it_is_night = next_sunrise_datetime < next_sunset_datetime
    print("It's night." if it_is_night else "It's day.")
    

    Notes

    • For some reason lat and lon need to be strings but ephem does not complain if they are floats.
    • For best results, you might want to get the current air temperature and air pressure.

    Prerequisites

    This should work with at least Python 2.7 (with pip-2.7 install pyephem) and Python 3.2 (with pip-3.2 install ephem).

    Make sure to have a network time protocol client running on the system. E.g. on Debian Linux:

    $ sudo apt-get install ntp
    $ sudo /etc/init.d/ntp start
    

    Make sure to have the correct timezone set on your system. E.g. on Debian Linux:

    $ sudo dpkg-reconfigure tzdata
    
    0 讨论(0)
  • 2021-02-05 06:46

    You can do as I did and use this public domain Sun.py module to compute the position of the sun relative to positions on the Earth. It's pretty old, but has worked well for me for many years. I made a few superficial modifications to it to be more up-to-date with Python 2.7, such as making the few classes in it new-style, but for the most part it's unchanged.

    Here's one module I created, called sunriseset.py, which shows how to use it to calculate the sunrise and sunset times for a specific location given its geographic coordinates and timezone. The referenced timezone module is an implementation of the tzinfo abstract base class described in the datetime module's documentation on tzinfoobjects.

    # -*- coding: iso-8859-1 -*-
    import datetime
    import timezone  # concrete tzinfo subclass based on the Python docs
    import math
    from Sun import Sun
    
    __all__ = ['getsuninfo', 'Place']
    
    class Place(object):
        def __init__(self, name, coords, tz=timezone.Pacific):
            self.name = name        # string
            self.coords = coords    # tuple (E/W long, N/S lat)
            self.tz = tz            # tzinfo constant
    
    def _hoursmins(hours):
        """Convert floating point decimal time in hours to integer hrs,mins"""
        frac,h = math.modf(hours)
        m = round(frac*60, 0)
        if m == 60: # rounded up to next hour
            h += 1; m = 0
        return int(h),int(m)
    
    def _ymd(date):
        """Return y,m,d from datetime object as tuple"""
        return date.timetuple()[:3]
    
    def getsuninfo(location, date=None):
        """Return local datetime of sunrise, sunset, and length of day in hrs,mins)"""
        if date == None:
            querydate = datetime.date.today()
        else: # date given should be datetime instance
            querydate = date
    
        args = _ymd(querydate) + location.coords
        utcrise, utcset = Sun().sunRiseSet(*args)
        daylength = Sun().dayLength(*args)
        hrs,mins = _hoursmins(daylength)
    
        risehour, risemin = _hoursmins(utcrise)
        sethour, setmin   = _hoursmins(utcset)
    
        # convert times to timedelta values (ie from midnight utc of the date)
        midnight = datetime.datetime(tzinfo=timezone.utc, *_ymd(querydate))
        deltarise = datetime.timedelta(hours=risehour, minutes=risemin)
        utcdatetimerise = midnight+deltarise
        deltaset = datetime.timedelta(hours=sethour, minutes=setmin)
        utcdatetimeset  = midnight+deltaset
    
        # convert results from UTC time to local time of location
        localrise = utcdatetimerise.astimezone(location.tz)
        localset  = utcdatetimeset.astimezone(location.tz)
    
        return localrise, localset, hrs, mins
    
    if __name__ == "__main__":
        import datetime, timezone
    
        def unittest(location, testdate):
            risetime, settime, hrs, mins = getsuninfo(location, testdate)
    
            print "Location:", location.name
            print "Date:", testdate.strftime("%a %x")
            print risetime.strftime("Sunrise %I:%M %p"), settime.strftime("- Sunset %I:%M %p (%Z)")
            print "daylight: %d:%02d" % (hrs,mins)
            print
    
        place = Place("My House", (-121.990278, 47.204444), timezone.Pacific)
    
        # test dates just before and after DST transitions
        print "pre 2007"
        print "========="
        unittest(place, datetime.date(2006, 4, 1))
        unittest(place, datetime.date(2006, 4, 2))
        unittest(place, datetime.date(2006, 10, 28))
        unittest(place, datetime.date(2006, 10, 29))
    
        print "2007"
        print "========="
        unittest(place, datetime.date(2007, 3, 10))
        unittest(place, datetime.date(2007, 3, 11))
        unittest(place, datetime.date(2007, 11, 3))
        unittest(place, datetime.date(2007, 11, 4))
    
    0 讨论(0)
  • 2021-02-05 07:01

    A concise description of an algorithm to calculate the sunrise and sunset is provided by the United States Naval Observatory, available here:

    http://edwilliams.org/sunrise_sunset_algorithm.htm

    In addition to providing the date and location, you also need to select a Zenith angle (at which the sun will be considered to have "risen" or "set") - the page linked has several options.


    Update

    Because the linked page is no longer available, I am quoting its text below. Note that the formulae included are in a pseudo-code-like form, rather than JavaScript.

    Source:
        Almanac for Computers, 1990
        published by Nautical Almanac Office
        United States Naval Observatory
        Washington, DC 20392
    
    Inputs:
        day, month, year:      date of sunrise/sunset
        latitude, longitude:   location for sunrise/sunset
        zenith:                Sun's zenith for sunrise/sunset
          offical      = 90 degrees 50'
          civil        = 96 degrees
          nautical     = 102 degrees
          astronomical = 108 degrees
    
        NOTE: longitude is positive for East and negative for West
            NOTE: the algorithm assumes the use of a calculator with the
            trig functions in "degree" (rather than "radian") mode. Most
            programming languages assume radian arguments, requiring back
            and forth convertions. The factor is 180/pi. So, for instance,
            the equation RA = atan(0.91764 * tan(L)) would be coded as RA
            = (180/pi)*atan(0.91764 * tan((pi/180)*L)) to give a degree
            answer with a degree input for L.
    
    
    1. first calculate the day of the year
    
        N1 = floor(275 * month / 9)
        N2 = floor((month + 9) / 12)
        N3 = (1 + floor((year - 4 * floor(year / 4) + 2) / 3))
        N = N1 - (N2 * N3) + day - 30
    
    2. convert the longitude to hour value and calculate an approximate time
    
        lngHour = longitude / 15
    
        if rising time is desired:
          t = N + ((6 - lngHour) / 24)
        if setting time is desired:
          t = N + ((18 - lngHour) / 24)
    
    3. calculate the Sun's mean anomaly
    
        M = (0.9856 * t) - 3.289
    
    4. calculate the Sun's true longitude
    
        L = M + (1.916 * sin(M)) + (0.020 * sin(2 * M)) + 282.634
        NOTE: L potentially needs to be adjusted into the range [0,360) by adding/subtracting 360
    
    5a. calculate the Sun's right ascension
    
        RA = atan(0.91764 * tan(L))
        NOTE: RA potentially needs to be adjusted into the range [0,360) by adding/subtracting 360
    
    5b. right ascension value needs to be in the same quadrant as L
    
        Lquadrant  = (floor( L/90)) * 90
        RAquadrant = (floor(RA/90)) * 90
        RA = RA + (Lquadrant - RAquadrant)
    
    5c. right ascension value needs to be converted into hours
    
        RA = RA / 15
    
    6. calculate the Sun's declination
    
        sinDec = 0.39782 * sin(L)
        cosDec = cos(asin(sinDec))
    
    7a. calculate the Sun's local hour angle
    
        cosH = (cos(zenith) - (sinDec * sin(latitude))) / (cosDec * cos(latitude))
    
        if (cosH >  1) 
          the sun never rises on this location (on the specified date)
        if (cosH < -1)
          the sun never sets on this location (on the specified date)
    
    7b. finish calculating H and convert into hours
    
        if if rising time is desired:
          H = 360 - acos(cosH)
        if setting time is desired:
          H = acos(cosH)
    
        H = H / 15
    
    8. calculate local mean time of rising/setting
    
        T = H + RA - (0.06571 * t) - 6.622
    
    9. adjust back to UTC
    
        UT = T - lngHour
        NOTE: UT potentially needs to be adjusted into the range [0,24) by adding/subtracting 24
    
    10. convert UT value to local time zone of latitude/longitude
    
        localT = UT + localOffset
    
    0 讨论(0)
提交回复
热议问题