Схід і захід сонця


12

Я трохи романтик, я люблю виводити дружину, щоб побачити схід і захід сонця в тому місці, де ми знаходимось. Заради цієї вправи, скажімо, у мене немає коду, який би міг підказати мені час заходу або сходу сонця на будь-яку дату, широту і довготу, в якій я б знаходився.

Ваше завдання, кодери, - створити найменший можливий код, який займає десяткову широту і довготу (приймається в градусах N і W, тому градуси S і E будуть вважатися негативом) і дату у форматі YYYY-MM-DD ( з 1 січня 2000 р.) і випльовуватиметься двічі у форматі 24 годин на схід і захід сонця.

наприклад, на сьогодні в Сіднеї, Австралія

riseset -33.87 -151.2 2013-12-27

05:45 20:09

Бонуси: -100, якщо ви можете скористатися висотою, -100, якщо ви зможете визначити економію денного світла

Код ПОВИНЕН виплюнути рази у відповідному часовому поясі, зазначеному у вході, виходячи із широти та довготи АБО у власному часовому поясі клієнтської машини.


3
Зачекайте, що, ми повинні зробити пошук [широта x довгота] => [часовий пояс]? Чи отримуємо для цього файл даних? Або сервер, до якого ми можемо отримати доступ? Або є мова, в яку вбудовані такі речі? Чи можете ви сказати нам, який з них? Або ми повинні запам'ятати межі часового поясу? До якої точності? Звідки ми беремо ці дані? Чи усвідомлюєте ви, що ці дані займуть велику частину коду? А як щодо координат, які випадають саме на межі часового поясу? Скажіть, географічні полюси? Крім того, яка поведінка дозволена, коли вхід є полярною областю протягом полярної ночі / дня? А як щодо позамісних координат?
Джон Дворак

Я люблю виклик , щоб обчислити горизонт , заснований на точці вище ідеалізованої сфері, але я ненавиджу пов'язаний з ним виклик знайти, ручний компрес, decopmress програмно , а потім подивитися в, часовий пояс LookUp карту. Якщо, звичайно, ми не можемо використовувати ідеалізовані часові пояси (зміщення вибрано таким чином, щоб сонце було найбільше під полудень, тоді воно округлене до найближчої години).
Джон Дворак

1
@JanDvorak Використовуйте все, що можете, якщо ви використовуєте мову, ви можете скористатися часовим поясом клієнта, то всіма силами зробіть це ...
WallyWest

1
Яка бажана поведінка для полярних регіонів, коли це полярний день / ніч?
Джон Дворак

1
Ось інструмент, який робить саме те саме: weatherimages.org/latlonsun.html
Ейза Аділь

Відповіді:


4

Я витратив досить багато часу на написання цього:

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

Тепер це ще не функціонально (я викрутив деякі розрахунки) - я повернусь до нього пізніше (якщо я все-таки матиму сміливість), щоб завершити / прокоментувати його .

Також кілька цікавих ресурсів, які я знайшов під час дослідження цієї теми:


3
Я щойно побачив ваш коментар # It's late, I'm tired, and OP is a prick for asking me to do this. до цього завдання не було зобов’язане ... Будь ласка, не вводьте такі коментарі у свій код ... Це не сприятливо стосується інших кодерів ... включаючи мене. Я захоплююсь тим, що ви
надіслали його гарячим переходом

@ Eliseod'Annunzio Ви маєте свої вибачення.
Денеб

@ Eliseod'Annunzio Я не збирався тебе ображати. Я також хотів би подякувати вам за те, що ви дали мені абсолютно фантастичну ідею для дослідження та кодування. Тепер я хочу перетворити це на самостійний модуль python (з аргументами sys тощо). Це виявляється трохи складніше, ніж я думав раніше, але я маю намір це витягнути. Ще раз дякую вам.
Денеб

@ Алекс, ти розумієш, що цьому виклику рік? Я впевнений, що він переміг.
mbomb007

@ mbomb007: не усвідомлював.
Олексій А.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.