Sonnenaufgang und Sonnenuntergang

12

Ich bin ein bisschen romantisch, ich liebe es, mit meiner Frau die Sonnenaufgänge und Sonnenuntergänge an dem Ort zu erleben, an dem wir uns befinden. Für diese Übung kann ich sagen, dass ich keinen Code habe, der mir die Zeit von Sonnenuntergang oder Sonnenaufgang für das Datum, den Breiten- und Längengrad angibt, in dem ich mich gerade befinde.

Ihre Aufgabe, Codierer, ist es, den kleinstmöglichen Code zu generieren, der einen dezimalen Breiten- und Längengrad (in Grad N und W genommen, also werden Grad S und E als Negative genommen) und ein Datum im Format JJJJ-MM-TT ( ab dem 1. Januar 2000) und es wird zweimal im 24-Stunden-Format für den Sonnenaufgang und Sonnenuntergang ausgespuckt.

zB Für heute in Sydney, Australien

riseset -33.87 -151.2 2013-12-27

05:45 20:09

Boni: -100, wenn Sie die Höhe berücksichtigen können -100, wenn Sie die Sommerzeit berücksichtigen können

Der Code MUSS die Zeiten in der relevanten Zeitzone ausspucken, die in der Eingabe angegeben ist, basierend auf dem Breiten- und Längengrad ODER in der eigenen Zeitzone des Client-Computers.

WallyWest
quelle
3
Warten Sie, was, wir müssen eine Suche nach [Breite x Länge] => [Zeitzone] durchführen? Bekommen wir dafür eine Datendatei? Oder auf einen Server, auf den wir zugreifen können? Oder gibt es eine Sprache, in der solche Dinge eingebaut sind? Können Sie uns sagen, welche? Oder müssen wir uns die Grenzen der Zeitzone merken? Mit welcher Präzision? Woher bekommen wir diese Daten? Ist Ihnen klar, dass diese Daten den größten Teil der Codelänge einnehmen? Was ist mit Koordinaten, die genau auf die Zeitzonengrenze fallen? Sagen wir, die geografischen Pole? Welches Verhalten ist zulässig, wenn der Eingang während einer polaren Nacht / eines polaren Tages eine polare Region ist? Was ist mit Koordinaten außerhalb des Bereichs?
John Dvorak
Ich würde die Herausforderung lieben , den Horizont basierend auf einem Punkt über einer idealisierten Kugel zu berechnen, aber ich hasse die damit verbundene Herausforderung, eine Zeitzonensuchkarte zu finden, von Hand zu komprimieren, programmatisch zu dekopieren und dann nachzuschlagen. Es sei denn, wir können natürlich auch idealisierte Zeitzonen verwenden (der Versatz wird so gewählt, dass die Sonne am Mittag am höchsten ist, dann wird sie auf die nächste Stunde gerundet).
John Dvorak
1
@JanDvorak Verwenden Sie alles, was Sie können, wenn die von Ihnen verwendete Sprache die Zeitzone des Clients ausnutzt, dann tun Sie dies auf jeden Fall ...
WallyWest
1
Was ist das gewünschte Verhalten für Polarregionen, wenn es ein polarer Tag / Nacht ist?
John Dvorak
1
Hier ist ein Tool, das genau dasselbe tut: weatherimages.org/latlonsun.html
Eisa Adil

Antworten:

4

Ich habe einige Zeit damit verbracht, Folgendes zu schreiben:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from math import *


class RiseSet(object):

    __ZENITH = {'official': 90.833,
                'civil': '96',
                'nautical': '102',
                'astronomical': '108'}

    def __init__(self, day, month, year, latitude, longitude, daylight=False,
                 elevation=840, zenith='official'):
        ''' elevation is set to 840 (m) because that is the mean height of land above the sea level '''

        if abs(latitude) > 63.572375290155:
            raise ValueError('Invalid latitude: {0}.'.format(latitude))

        if zenith not in self.__ZENITH:
            raise ValueError('Invalid zenith value, must be one of {0}.'.format
                            (self.__ZENITH.keys()))

        self.day = day
        self.month = month
        self.year = year
        self.latitude = latitude
        self.longitude = longitude
        self.daylight = daylight
        self.elevation = elevation
        self.zenith = zenith

    def getZenith(self):
        return cos(radians(self.__ZENITH[self.zenith]))

    def dayOfTheYear(self):
        n0 = floor(275*self.month/9)
        n1 = floor((self.month + 9) / 12)
        n2 = (1 + floor((self.year - 4*floor(self.year/4) + 2) / 3))
        return n0 - (n1*n2) + self.day - 30

    def approxTime(self):
        sunrise = self.dayOfTheYear() + ((6 - (self.longitude/15.0)) / 24)
        sunset = self.dayOfTheYear() + ((18 - (self.longitude/15.0)) / 24)
        return (sunrise, sunset)

    def sunMeanAnomaly(self):
        sunrise = (0.9856 * self.approxTime()[0]) - 3.289
        sunset = (0.9856 * self.approxTime()[1]) - 3.289
        return (sunrise, sunset)

    def sunTrueLongitude(self):
        sma = self.sunMeanAnomaly()
        sunrise = sma[0] + (1.916*sin(radians(sma[0]))) + \
                  (0.020*sin(radians(2*sma[0]))) + 282.634

        if sunrise < 0:
            sunrise += 360
        if sunrise > 360:
            sunrise -= 360

        sunset = sma[1] + (1.916*sin(radians(sma[1]))) + \
                 (0.020*sin(radians(2*sma[1]))) + 282.634

        if sunset <= 0:
            sunset += 360
        if sunset > 360:
            sunset -= 360

        return (sunrise, sunset)

    def sunRightAscension(self):
        stl = self.sunTrueLongitude()
        sunrise = atan(radians(0.91764*tan(radians(stl[0]))))

        if sunrise <= 0:
            sunrise += 360
        if sunrise > 360:
            sunrise -= 360

        sunset = atan(radians(0.91764*tan(radians(stl[1]))))

        if sunset <= 0:
            sunset += 360
        if sunset > 360:
            sunset -= 360

        sunrise_stl_q = (floor(stl[0]/90)) * 90
        sunrise_ra_q = (floor(sunrise/90)) * 90
        sunrise = sunrise + (sunrise_stl_q - sunrise_ra_q)
        sunrise = sunrise/15.0

        sunset_stl_q = (floor(stl[1]/90)) * 90
        sunset_ra_q = (floor(sunset/90)) * 90
        sunset = sunrise + (sunset_stl_q - sunset_ra_q)
        sunset /= 15.0

        return (sunrise, sunset)

    def sunDeclination(self):
        sunrise_sin_dec = 0.39782 * sin(radians(self.sunTrueLongitude()[0]))
        sunrise_cos_dec = cos(radians(asin(radians(sunrise_sin_dec))))

        sunset_sin_dec = 0.39782 * sin(radians(self.sunTrueLongitude()[1]))
        sunset_cos_dec = cos(radians(asin(radians(sunrise_sin_dec))))

        return (sunrise_sin_dec, sunrise_cos_dec,
                sunset_sin_dec, sunset_cos_dec)

    def sunHourAngle(self):
        sd = self.sunDeclination()
        sunrise_cos_h = (cos(radians(self.getZenith())) - (sd[0]* \
                         sin(radians(self.latitude))) / (sd[1]* \
                         cos(radians(self.latitude))))
        if sunrise_cos_h > 1:
            raise Exception('The sun never rises on this location.')

        sunset_cos_h = (cos(radians(self.getZenith())) - (sd[2]* \
                         sin(radians(self.latitude))) / (sd[3]* \
                         cos(radians(self.latitude))))
        if sunset_cos_h < -1:
            raise Exception('The sun never sets on this location.')

        sunrise = 360 - acos(radians(sunrise_cos_h))
        sunrise /= 15.0

        sunset = acos(radians(sunrise_cos_h))
        sunset /= 15.0

        return (sunrise, sunset)

    def localMeanTime(self):
        sunrise = self.sunHourAngle()[0] + self.sunRightAscension()[0] - \
                 (0.06571*self.approxTime()[0]) - 6.622
        sunset = self.sunHourAngle()[1] + self.sunRightAscension()[1] - \
                 (0.06571*self.approxTime()[1]) - 6.622
        return (sunrise, sunset)

    def convertToUTC(self):
        sunrise = self.localMeanTime()[0] - (self.longitude/15.0)

        if sunrise <= 0:
            sunrise += 24
        if sunrise > 24:
            sunrise -= 24

        sunset = self.localMeanTime()[1] - (self.longitude/15.0)

        if sunset <= 0:
            sunset += 24
        if sunset > 24:
            sunset -= 24

        return (sunrise, sunset)

    def __str__(self):
        return None

Jetzt ist es noch nicht funktionsfähig (ich habe einige Berechnungen vermasselt) - ich werde später darauf zurückkommen (wenn ich noch den Mut habe), es zu vervollständigen / zu kommentieren .

Außerdem einige interessante Ressourcen, die ich bei der Recherche des Themas gefunden habe:

Deneb
quelle
3
Ich habe gerade Ihren Kommentar von gesehen. # It's late, I'm tired, and OP is a prick for asking me to do this. Es gab keine Verpflichtung, diese Aufgabe zu erledigen. Bitte fügen Sie solche Kommentare nicht in Ihren Code ein. Es passt nicht gut zu anderen Programmierern, einschließlich mir. Ich bewundere die Tatsache, dass Sie ihm einen
brandheißen Start verpasst haben
@ Eliseod'Annunzio Du hast meine Entschuldigung.
Deneb
@ Eliseod'Annunzio Ich wollte dich nicht beleidigen. Ich möchte mich auch bei Ihnen dafür bedanken, dass Sie mir eine absolut fantastische Idee für Recherche und Code gegeben haben. Jetzt möchte ich daraus ein eigenständiges Python-Modul machen (mit sys-Argumenten und so weiter). Es stellt sich als etwas komplizierter heraus, als ich vorher gedacht hatte, aber ich beabsichtige, dies durchzuziehen. Danke nochmal.
Deneb
@Alex, ist dir klar, dass diese Herausforderung ein Jahr alt ist? Ich bin mir ziemlich sicher, dass er gewonnen hat.
mbomb007
@ mbomb007: Hab's nicht gemerkt.
Alex A.