Lever et coucher de soleil

12

Je suis un peu romantique, j'adore emmener ma femme pour voir les levers et couchers de soleil à l'endroit où nous sommes situés. Pour cet exercice, disons que je n'ai pas de code qui puisse me dire l'heure du coucher ou du lever du soleil pour la date, la latitude et la longitude dans lesquelles je me trouverais.

Votre tâche, codeurs, est de générer le plus petit code possible qui prend une latitude et une longitude décimales (prises en degrés N et W, donc les degrés S et E seront pris comme négatifs) et une date au format AAAA-MM-JJ ( à partir du 1er janvier 2000) et il crachera deux fois au format 24h pour le lever et le coucher du soleil.

par exemple pour aujourd'hui à Sydney, Australie

riseset -33.87 -151.2 2013-12-27

05:45 20:09

Bonus: -100 si vous pouvez prendre en compte l'élévation -100 si vous pouvez prendre en compte l'heure d'été

Le code DOIT cracher des heures dans le fuseau horaire pertinent spécifié dans l'entrée en fonction de la latitude et de la longitude OU dans le fuseau horaire de la machine cliente.

WallyWest
la source
3
Attendez, quoi, nous devons faire une recherche [latitude x longitude] => [fuseau horaire]? Avons-nous un fichier de données pour cela? Ou un serveur auquel nous pouvons accéder? Ou existe-t-il un langage qui intègre de telles choses? Pouvez-vous nous dire lequel? Ou nous devons mémoriser les limites de fuseau horaire? Avec quelle précision? Où obtenons-nous ces données? Vous rendez-vous compte que ces données occuperont la majeure partie de la longueur du code? Qu'en est-il des coordonnées qui tombent exactement sur la limite du fuseau horaire? Dis, les pôles géographiques? De plus, quel comportement est autorisé lorsque l'entrée est une région polaire pendant une nuit / jour polaire? Qu'en est-il des coordonnées hors de portée?
John Dvorak
J'aime le défi de calculer l'horizon basé sur un point au- dessus d' une sphère idéalisée, mais je déteste le défi associé à trouver, main-compress, puis decopmress programatically chercher dans un fuseau horaire de recherche carte. À moins, bien sûr, que nous puissions utiliser des fuseaux horaires idéalisés (le décalage est choisi de sorte que le soleil soit le plus élevé pendant midi, puis il est arrondi à l'heure la plus proche) également.
John Dvorak
1
@JanDvorak Utilisez tout ce que vous pouvez, si la langue que vous utilisez peut exploiter le fuseau horaire du client, alors faites-le par tous les moyens ...
WallyWest
1
Quel est le comportement souhaité pour les régions polaires lorsqu'il s'agit d'un jour / nuit polaire?
John Dvorak
1
Voici un outil qui fait exactement la même chose: weatherimages.org/latlonsun.html
Eisa Adil

Réponses:

4

J'ai passé pas mal de temps à écrire ceci:

#!/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

Maintenant ce n'est pas encore fonctionnel (j'ai foiré quelques calculs) - j'y reviendrai plus tard (si j'ai encore le courage) de le compléter / commenter .

Aussi, quelques ressources intéressantes que j'ai trouvées en faisant des recherches sur le sujet:

Deneb
la source
3
Je viens de voir votre commentaire sur # It's late, I'm tired, and OP is a prick for asking me to do this. Il n'y avait aucune obligation de faire cette tâche ... S'il vous plaît ne mettez pas de commentaires comme celui-ci dans votre code ... Il ne convient pas aux autres codeurs ... y compris moi. J'admire le fait que vous lui ayez donné un coup de
fouet
@ Eliseod'Annunzio Vous avez mes excuses.
Deneb
@ Eliseod'Annunzio Je n'avais pas l'intention de vous offenser. Je voudrais également vous remercier de m'avoir donné une idée absolument fantastique pour la recherche et le codage. Maintenant, je veux transformer cela en un module python autonome (avec des arguments sys et ainsi de suite). Cela s'avère un peu plus compliqué que je ne le pensais auparavant, mais j'ai l'intention de retirer cela. Merci encore.
Deneb
@Alex, vous rendez-vous compte que ce défi a un an? Je suis quasiment sûr qu'il a gagné.
mbomb007
@ mbomb007: Je ne m'en suis pas rendu compte.
Alex A.