Nascer e pôr do sol


12

Sou um pouco romântica, adoro levar minha esposa para ver o nascer e o pôr do sol no local em que estamos localizados. Para o exercício deste exercício, digamos que não possuo código que possa me dizer a hora do pôr do sol ou do nascer do sol em qualquer data, latitude e longitude em que eu esteja.

Sua tarefa, codificadores, é gerar o menor código possível, com latitude e longitude decimal (tirada nos graus N e W, para que os graus S e E sejam considerados negativos) e uma data no formato AAAA-MM-DD ( a partir de 1º de janeiro de 2000) e será emitido duas vezes no formato 24 horas para o nascer e o pôr do sol.

Por exemplo, hoje em Sydney, Austrália

riseset -33.87 -151.2 2013-12-27

05:45 20:09

Bônus: -100 se você pode levar em consideração a elevação -100 se você pode levar em consideração o horário de verão

O código DEVE citar os horários no fuso horário relevante especificado na entrada com base na latitude e longitude OU no fuso horário da máquina do cliente.


3
Espere, temos que fazer uma pesquisa [latitude x longitude] => [fuso horário]? Temos um arquivo de dados para isso? Ou um servidor que podemos acessar? Ou existe uma linguagem que tenha essas coisas incorporadas? Você pode nos dizer qual? Ou temos que memorizar os limites do fuso horário? Com que precisão? Onde obtemos esses dados? Você percebe que esses dados ocupam a maior parte do comprimento do código? E as coordenadas que caem exatamente no limite do fuso horário? Digamos, os pólos geográficos? Além disso, qual comportamento é permitido quando a entrada é uma região polar durante uma noite / dia polar? E as coordenadas fora de alcance?
precisa

Eu adoraria o desafio de calcular o horizonte com base em um ponto acima de uma esfera idealizada, mas odeio o desafio associado de encontrar, comprimir à mão, descomprimir programaticamente e depois procurar em um mapa de pesquisa de fuso horário. A menos que, é claro, possamos usar fusos horários idealizados (o deslocamento é escolhido para que o sol seja o mais alto durante o meio-dia, depois é arredondado para a hora mais próxima).
John Dvorak

1
@JanDvorak Use o que você pode, se a linguagem que você usa pode explorar o fuso horário do cliente, em seguida, por todos os meios fazê-lo ...
Wally West

1
Qual é o comportamento desejado para regiões polares quando é dia / noite polares?
precisa

1
Aqui está uma ferramenta que faz exatamente o mesmo: weatherimages.org/latlonsun.html
Eisa Adil

Respostas:


4

Passei bastante tempo escrevendo isso:

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

Agora ainda não está funcional (eu estraguei alguns cálculos) - voltarei mais tarde (se ainda tiver coragem) para concluir / comentar .

Além disso, alguns recursos interessantes que encontrei ao pesquisar o assunto:


3
Acabei de ver seu comentário de # It's late, I'm tired, and OP is a prick for asking me to do this. Não havia nenhuma obrigação de executar esta tarefa ... Por favor, não coloque comentários como este em seu código ... Ele não é favorável a outros codificadores ... inclusive a mim. Eu admiro o fato de que você dada por um vermelho quente, e os outros links que você forneceu, mas por favor, não use comentários como este nunca mais ...
Wally West

@ Eliseod'Annunzio Você tem minhas desculpas.
Deneb

@ Eliseod'Annunzio Eu não pretendia ofendê-lo. Também gostaria de agradecer por me dar uma idéia absolutamente fantástica para pesquisar e codificar. Agora eu quero transformar isso em um módulo python independente (com argumentos sys e assim por diante). Isso acaba sendo um pouco mais complicado do que eu pensava anteriormente, mas pretendo fazer isso. Mais uma vez obrigado.
Deneb

@ Alex, você percebe que esse desafio tem um ano? Tenho certeza que ele ganhou.
mbomb007

@ mbomb007: Não percebi.
Alex A.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.