Completed
Push — dev ( 91c66b...5706ca )
by Patrik
22s queued 17s
created

solph._helpers.create_time_index()   B

Complexity

Conditions 6

Size

Total Lines 71
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 22
dl 0
loc 71
rs 8.4186
c 0
b 0
f 0
cc 6
nop 4

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
# -*- coding: utf-8 -*-
2
3
"""
4
Private helper functions.
5
6
SPDX-FileCopyrightText: Uwe Krien <[email protected]>
7
SPDX-FileCopyrightText: Simon Hilpert
8
SPDX-FileCopyrightText: Cord Kaldemeyer
9
SPDX-FileCopyrightText: Stephan Günther
10
SPDX-FileCopyrightText: Birgit Schachler
11
SPDX-FileCopyrightText: David Fuhrländer
12
SPDX-FileCopyrightText: Johannes Röder
13
14
SPDX-License-Identifier: MIT
15
16
"""
17
18
import calendar
19
import datetime
20
from warnings import warn
21
22
import pandas as pd
23
from oemof.tools import debugging
24
25
26
def check_node_object_for_missing_attribute(obj, attribute):
27
    """Raises a predefined warning if object does not have attribute.
28
29
    Arguments
30
    ---------
31
32
    obj : python object
33
    attribute : (string) name of the attribute to test for
34
35
    """
36
    if not getattr(obj, attribute):
37
        warn_if_missing_attribute(obj, attribute)
38
39
40
def warn_if_missing_attribute(obj, attribute):
41
    """Raises warning if attribute is missing for given object"""
42
    msg = (
43
        "Attribute <{0}> is missing in Node <{1}> of {2}.\n"
44
        "If this is intended and you know what you are doing you can"
45
        "disable the SuspiciousUsageWarning globally."
46
    )
47
    warn(
48
        msg.format(attribute, obj.label, type(obj)),
49
        debugging.SuspiciousUsageWarning,
50
    )
51
52
53
def create_time_index(
54
    year: int = None,
55
    interval: float = 1,
56
    number: int = None,
57
    start: datetime.date = None,
58
):
59
    """
60
    Create a datetime index for one year.
61
62
    Notes
63
    -----
64
    To create 8760 hourly intervals for a non leap year a datetime index with
65
    8761 time points need to be created. So the number of time steps is always
66
    the number of intervals plus one.
67
68
    Parameters
69
    ----------
70
    year : int, datetime
71
        The year of the index.
72
        Used to automatically set start and number for the specific year.
73
    interval : float
74
        The time interval in hours e.g. 0.5 for 30min or 2 for a two hour
75
        interval (default: 1).
76
    number : int
77
        The number of time intervals. By default number is calculated to create
78
        an index of one year. For a shorter or longer period the number of
79
        intervals can be set by the user.
80
    start : datetime.datetime or datetime.date
81
        Optional start time. If start is not set, 00:00 of the first day of
82
        the given year is the start time.
83
84
    Examples
85
    --------
86
    >>> len(create_time_index(2014))
87
    8761
88
    >>> len(create_time_index(2012))  # leap year
89
    8785
90
    >>> len(create_time_index(2014, interval=0.5))
91
    17521
92
    >>> len(create_time_index(2014, interval=0.5, number=10))
93
    11
94
    >>> len(create_time_index(2014, number=10))
95
    11
96
    >>> str(create_time_index(2014, interval=0.5, number=10)[-1])
97
    '2014-01-01 05:00:00'
98
    >>> str(create_time_index(2014, interval=2, number=10)[-1])
99
    '2014-01-01 20:00:00'
100
    """
101
    if number is None:
102
        if calendar.isleap(year):
103
            hours_in_year = 8784
104
        else:
105
            hours_in_year = 8760
106
        number = round(hours_in_year / interval)
107
    if start is not None:
108
        if year is not None:
109
            raise ValueError(
110
                "Arguments 'start' and 'year' are mutually exclusive."
111
            )
112
    else:
113
        start = f"1/1/{year}"
114
    try:
115
        time_index = pd.date_range(
116
            start, periods=number + 1, freq=f"{interval}h"
117
        )
118
    except ValueError:
119
        # Pandas <2.2 compatibility
120
        time_index = pd.date_range(
121
            start, periods=number + 1, freq=f"{interval}H"
122
        )
123
    return time_index
124