Giter Club home page Giter Club logo

tzupdate's Introduction

tzupdate | Tests

tzupdate is a fully automated utility to set the system time using geolocation.

Features

  • Small, easy to understand codebase
  • Queries multiple geolocation services in parallel and returns the first with a successful result
  • Protects against directory traversal and invalid results when linking /etc/localtime

Installation

cargo install tzupdate

Usage

# tzupdate
Set system timezone to Europe/London.

Internally, this geolocates you, gets the timezone for that geolocation, and then updates the system's local time zone.

You can see what tzupdate would do without actually doing it by passing -p, and specify an alternative IP address by using -i. This is not an exhaustive list of options, see tzupdate --help for that.

tzupdate's People

Contributors

abdullahdevrel avatar cdown avatar dependabot[bot] avatar jbrockmendel avatar st0rmingbr4in avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tzupdate's Issues

Error Exception on Fail to connect to Internet

the tzupdate binary when used with Internet works really well, and hat off to all the developers. But, there is still one nasty problems. Whenever there is no Internet connection for the socket to open to such as error resolving DNS, or no connected iinterface, it thrown out a nasty python script error, and it continued on to try to reconnect at lightening speed. Maybe developers team can put a lid to the loop like 3 loops, if still error, just print out an one line error telling us users that no Internet or more specific issues.

Integrate Google Maps geolocation api

The current implementation works fine on a lot of cases, but VPNs and mobile networks will often give you a wrong location.
Using the Google Maps geolocation API on devices with a WIFI card would improve the accuracy a lot. The main problem with this is ofcourse that this API requires an API key, but this could be read from a file.

https://developers.google.com/maps/documentation/geolocation/intro

This is also something I could personally work on, and submit a pull request.

Installation package for distributions

This is a great piece of software, little known.

For easier installation and distribution, it would be great to have this packaged in deb format for Ubuntu/Debian/Mint, and maybe as rpm/* for other distributions as well.

JSONDecodeError

I'm getting a JSONDecodeError when I run sudo tzupdate.
However, it still looks like it works though.

out.txt

first launch onAarch after clone from AUR and makepkg -si

Hi,

Just cloned tzupdate from https://aur.archlinux.org/tzupdate.git and executed makepkg -si which seemingly completed with no errors. I then got the following:
$ tzupdate -p
Traceback (most recent call last):
File "/usr/lib/python3.8/site-packages/tzupdate.py", line 64, in get_timezone
timezone = q.get(block=True, timeout=timeout)
File "/usr/lib/python3.8/multiprocessing/queues.py", line 108, in get
raise Empty
_queue.Empty

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/bin/tzupdate", line 11, in
load_entry_point('tzupdate==1.5.0', 'console_scripts', 'tzupdate')()
File "/usr/lib/python3.8/site-packages/tzupdate.py", line 279, in main
timezone = get_timezone(args.ip, timeout=args.timeout, services=services)
File "/usr/lib/python3.8/site-packages/tzupdate.py", line 66, in get_timezone
raise TimezoneAcquisitionError(
tzupdate.TimezoneAcquisitionError: No usable response from any API in 5.0 seconds

Invalid syntax

When I try to run any of the specified commands I get the following:

Traceback (most recent call last):
  File "/home/ubuntu/.local/bin/tzupdate", line 5, in <module>
    from tzupdate import main
  File "/home/ubuntu/.local/lib/python2.7/site-packages/tzupdate.py", line 69
    ) from None
         ^
SyntaxError: invalid syntax

Installed using Pip 20 on Python 2.7 for Ubuntu 16.04

"No module named 'tzupdate'"

Hello,
First of all thanks for making this! I have been using tzupdate for a while and it has worked fantastically well. Unfortunately it seems to break on Ubuntu 22.04-based distros (currently using KDE neon). If I try to launch tzupdate (sudo tzupdate), this is what happens:

Traceback (most recent call last):
  File "/usr/local/bin/tzupdate", line 5, in <module>
    from tzupdate import main
ModuleNotFoundError: No module named 'tzupdate'

Any idea what might be going on?
I have Python 3.10.6 installed and I installed tzupdate using pip install -U tzupdate.

Thank you!

version 2.0.0 compatibility issues python2/3 symlink

After updating to 2.0.0, an invalid syntax error poped

→ sudo tzupdate
Traceback (most recent call last):
  File "/home/tgeo/.local/bin/tzupdate", line 5, in <module>
    from tzupdate import main
  File "/home/tgeo/.local/lib/python2.7/site-packages/tzupdate.py", line 69
    ) from None
         ^
SyntaxError: invalid syntax

So after troubleshooting this looks like a python version error.
Specifically the script calls in the environment /usr/bin/python

→ cat /home/tgeo/.local/bin/tzupdate
#!/usr/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from tzupdate import main
if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
    sys.exit(main())

So the script makes the assumption that /usr/bin/python points to python3 but in Ubuntu 18.04.3 LTS and as a general good practice (according to PEP394) python symlink should point to python2 actually and not python3.

→ cat /etc/os-release | grep VERSION
VERSION="18.04.3 LTS (Bionic Beaver)"
VERSION_ID="18.04"
VERSION_CODENAME=bionic
tgeo-work:  ~ 
→ which python && which python2 && which python3
/usr/bin/python
/usr/bin/python2
/usr/bin/python3
tgeo-work:  ~ 
→ /usr/bin/python --version && /usr/bin/python2 --version && /usr/bin/python3 --version
Python 2.7.17
Python 2.7.17
Python 3.6.9

Shouldn't we follow the recommendation in the above mentioned PEP?

python2 will refer to some version of Python 2.x.
python3 will refer to some version of Python 3.x.
for the time being, all distributions should ensure that python refers to the same target as python2.

For a workaround, the moment I switched the shebang to /usr/bin/python3 in ~/.local/bin/tzupdate everything works, maybe it's worth it pushing this to the main branch too?

Thanks

SSL error message when running tzupdate with python 3.8

Here is the output of running sudo tzupdate:

Process Process-4:
Process Process-2:
Traceback (most recent call last):
  File "/usr/lib/python3.8/urllib/request.py", line 1319, in do_open
    h.request(req.get_method(), req.selector, req.data, headers,
  File "/usr/lib/python3.8/http/client.py", line 1230, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.8/http/client.py", line 1276, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.8/http/client.py", line 1225, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.8/http/client.py", line 1004, in _send_output
    self.send(msg)
  File "/usr/lib/python3.8/http/client.py", line 944, in send
    self.connect()
  File "/usr/lib/python3.8/http/client.py", line 1399, in connect
    self.sock = self._context.wrap_socket(self.sock,
  File "/usr/lib/python3.8/ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "/usr/lib/python3.8/ssl.py", line 1040, in _create
    self.do_handshake()
  File "/usr/lib/python3.8/ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:1108)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/usr/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib/python3.8/site-packages/tzupdate.py", line 84, in get_timezone_for_ip
    api_response_obj = urlopen(api_url)  # nosec
  File "/usr/lib/python3.8/urllib/request.py", line 222, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib/python3.8/urllib/request.py", line 525, in open
    response = self._open(req, data)
  File "/usr/lib/python3.8/urllib/request.py", line 542, in _open
    result = self._call_chain(self.handle_open, protocol, protocol +
  File "/usr/lib/python3.8/urllib/request.py", line 502, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.8/urllib/request.py", line 1362, in https_open
    return self.do_open(http.client.HTTPSConnection, req,
  File "/usr/lib/python3.8/urllib/request.py", line 1322, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:1108)>
Traceback (most recent call last):
  File "/usr/lib/python3.8/urllib/request.py", line 1319, in do_open
    h.request(req.get_method(), req.selector, req.data, headers,
  File "/usr/lib/python3.8/http/client.py", line 1230, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.8/http/client.py", line 1276, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.8/http/client.py", line 1225, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.8/http/client.py", line 1004, in _send_output
    self.send(msg)
  File "/usr/lib/python3.8/http/client.py", line 944, in send
    self.connect()
  File "/usr/lib/python3.8/http/client.py", line 1399, in connect
    self.sock = self._context.wrap_socket(self.sock,
  File "/usr/lib/python3.8/ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "/usr/lib/python3.8/ssl.py", line 1040, in _create
    self.do_handshake()
  File "/usr/lib/python3.8/ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:1108)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/usr/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib/python3.8/site-packages/tzupdate.py", line 84, in get_timezone_for_ip
    api_response_obj = urlopen(api_url)  # nosec
  File "/usr/lib/python3.8/urllib/request.py", line 222, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib/python3.8/urllib/request.py", line 525, in open
    response = self._open(req, data)
  File "/usr/lib/python3.8/urllib/request.py", line 542, in _open
    result = self._call_chain(self.handle_open, protocol, protocol +
  File "/usr/lib/python3.8/urllib/request.py", line 502, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.8/urllib/request.py", line 1362, in https_open
    return self.do_open(http.client.HTTPSConnection, req,
  File "/usr/lib/python3.8/urllib/request.py", line 1322, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:1108)>
Set system timezone to America/Regina.

It still works, but the error message is disconcerting.

Installed from AUR

Consider checking which timezone path the system uses

I use Arch, which sets the timezone via the /etc/localtime symbolic link.

Recently I had a calendar program which was displaying events in the wrong timezone, despite things like date and timedatectl showing the correct timezone. I couldn't figure out where it was getting the incorrect configuration from.

As it turns out, I had run tzupdate when I was in a different timezone, which both set the /etc/localtime link and wrote the timezone to /etc/timezone. Later, when I returned to my home timezone, I changed the timezone back using a different method, such that /etc/localtime was correct but the /etc/timezone file that tzupdate created still showed the wrong timezone. This was where the calendar program was getting the incorrect date from.

It would be nice if tzupdate only modified the file used by the system. The easiest solution would be to not touch either file unless they already exist, but I see in #11 that tzupdate intentionally accounts for the odd case of a system which has no timezone configured yet.

Instead, maybe the best option is to check /etc/issue, if the contents look Debian-ish set /etc/timezone, otherwise set /etc/localtime.

Error in tzupdate

Hello and thanks for your program,

I am getting the following error when running the script:

Traceback (most recent call last):
File "/usr/lib/python3.7/site-packages/tzupdate.py", line 64, in get_timezone
timezone = q.get(block=True, timeout=timeout)
File "/usr/lib/python3.7/multiprocessing/queues.py", line 105, in get
raise Empty
_queue.Empty

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/bin/tzupdate", line 11, in
load_entry_point('tzupdate==1.5.0', 'console_scripts', 'tzupdate')()
File "/usr/lib/python3.7/site-packages/tzupdate.py", line 279, in main
timezone = get_timezone(args.ip, timeout=args.timeout, services=services)
File "/usr/lib/python3.7/site-packages/tzupdate.py", line 67, in get_timezone
"No usable response from any API in {} seconds".format(timeout)
tzupdate.TimezoneAcquisitionError: No usable response from any API in 5.0 seconds

I have checked if I have an internet connection and I do.
Is this just me or has the api deprecated?

Thanks a lot.

Previous timezone not cleared

When /etc/timezone is updated, it seems to not be clearing any existing timezone that was written there before. Specifically, I ran into an issue where a device that had been in America/Los_Angeles came to America/New_York. That device's /etc/timezone then looked like this:

America/New_York
es

Installing with pip and running with sudo doesn't work

Background: I'm using Ubuntu 16.04. I installed pip itself without root (because I think that's not really needed, right?)

Issue: When I install tzupate via pip, it installs fine. But when I run with sudo, I get the error "tzupdate: command not found"

`http://ip-api.com/json/{ip}` gives inaccurate responses

successive runs of tzupdate was yielding different timezones.

I noticed that depending on which SERVICE endpoint returned first -- the timezone followed that query response

Perhaps instead of using the first response, you should gather as many non-timeout responses as possible, and have the app vote on which one is correct. In the event of a tie, don't update the timezone.

sudo vs real root

Hi,
this is not really an "issue", but rather, a question...

If I run:
tzupdate -a 64.37.57.114

Answer is:
Set system timezone to America/New_York.

Cool thing is, tzupdate also changed the time on my system!

date
Sun Jan 14 22:41:19 EST 2018

But, if I run tzupdate as regular, non-root user, using sudo:
sudo tzupdate -a 64.37.57.114

Answer is:
Set system timezone to America/New_York.

Which is what I want, but running the date command shows:

date
Mon Jan 15 03:42:48 UTC 2018

Why is it? Why is it NOT updating the time, when run through sudo?

Error when /etc/localtime doesn't exist

If I run tzupdate on a new machine that doesn't have a timezone set yet, it has a no such file or directory '/etc/localtime' error. Touching the file first makes it work as expected.

Autorun

Whereas the script runs great when executed manually, it'd be great for it to run automatically as soon as there is Internet access.

I have tried manually calling it from /etc/rc.local, but the timezone is not updated (is the Internet connection available at that point?)

Whatever the solution is, it would be great to have it automatically set up upon installation.

Add a service file to change the timezone on boot

This service file (timezone.service) could be included in the aur package so that the timezone is changed automatically (if the physical location of the machine is changed). This is not essential but could be useful. Thank you

`[Unit]
Description=Sets timezone automatically (needs internet connection)
Wants=network-online.target
After=network.target network-online.target

[Service]
ExecStart=/usr/bin/tzupdate

[Install]
WantedBy=multi-user.target
`

Add this terrific documentation

This answer on stackexchange was really close to the right solution in 2022.

It just needs some updating for python3 (i mean, installing like this sudo pip3 install -U tzupdate) and it would be good as gold

Debian10&Kali linux

It cannot be used on debian10 and kalilinux2021.2 systems, it will have a lot of errors.

Info DB account suspended, script fails

Any requests to the ipinfodb service used return a message like:

"ERROR;Your account has been suspended.;x.y.z.w;;;;;;0;0;"

It appears that the account whose keys are baked into the script has been suspended.

Taking the account keys as command-line params rather than distributing them in the script should solve that issue pretty well.

Network unreachable errors

If I run tzupdate -p following errors are shown (but the timzone gets detected):

Process Process-1:
Traceback (most recent call last):
  File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
    self.run()
  File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib/python2.7/site-packages/tzupdate.py", line 53, in get_timezone_for_ip
    api_response = requests.get(api_url).json()
  File "/usr/lib/python2.7/site-packages/requests/api.py", line 70, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/lib/python2.7/site-packages/requests/api.py", line 56, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "/usr/lib/python2.7/site-packages/requests/adapters.py", line 487, in send
    raise ConnectionError(e, request=request)
ConnectionError: HTTPConnectionPool(host='ip-api.com', port=80): Max retries exceeded with url: /json/ (Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x7f8685f06a90>: Failed to establish a new connection: [Errno 111] Connection refused',))
Process Process-2:
Traceback (most recent call last):
  File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
    self.run()
  File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib/python2.7/site-packages/tzupdate.py", line 53, in get_timezone_for_ip
    api_response = requests.get(api_url).json()
  File "/usr/lib/python2.7/site-packages/requests/api.py", line 70, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/lib/python2.7/site-packages/requests/api.py", line 56, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "/usr/lib/python2.7/site-packages/requests/adapters.py", line 487, in send
    raise ConnectionError(e, request=request)
ConnectionError: HTTPSConnectionPool(host='freegeoip.net', port=443): Max retries exceeded with url: /json/ (Caused by NewConnectionError('<requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x7f8685f06ad0>: Failed to establish a new connection: [Errno 101] Network unreachable',))
Detected timezone is Europe/Berlin.

Additional information:

  • OS: Alpine Linux 3.5.0
  • Python: Python 2.7.13

qestion

the tool works perfect <3

can u create another one for dns automatic update for the new IP?

it could be amazing too

thanks

ENH: API for get_timezone_for_ip

I have some not-that-old code that called tzname = tzupdate.get_timezone_for_ip() that is breaking after updating to the latest version. It looks like the same behavior is still available via the CLI via tzupdate -p, but I don't see a nice way to get the same behavior via python. Would a PR to restore that functionality (presumably under a new name) be accepted?

Add to documentation

It installed on raspbian by running
sudo pip install -U tzupdate

But it couldn't run, it reported a SyntaxError, it was fixed by uninstalling and installing with pip3

sudo pip uninstall tzupdate
sudo pip3 install -U tzupdate

Print detected timezone only

Hey, great project! The option --print-only will currently output "Set system timezone to WHATEVER.". For further processing in other software it would be handy to only return the timezone string. This could be either changed for print-only or done for an additional argument. Whatever you prefer ;) Thanks!

setup.py install fails due to missing maxminddb distribution

Installed /home/chris/git/tzupdate/sdist/lib/python3.4/site-packages/maxminddb_geolite2-2015.708-py3.4.egg
Searching for maxminddb
Best match: maxminddb geolite2-2015.0708
Downloading https://pypi.python.org/packages/source/m/maxminddb-geolite2/maxminddb-geolite2-2015.0708.tar.gz#md5=f4d113f89c9d5af25d7f6d67940dc796
Processing maxminddb-geolite2-2015.0708.tar.gz
Writing /tmp/easy_install-rfvi5ml5/maxminddb-geolite2-2015.0708/setup.cfg
Running maxminddb-geolite2-2015.0708/setup.py -q bdist_egg --dist-dir /tmp/easy_install-rfvi5ml5/maxminddb-geolite2-2015.0708/egg-dist-tmp-u2on_pk_
/home/chris/git/tzupdate/sdist/lib/python3.4/site-packages/setuptools/dist.py:285: UserWarning: Normalizing '2015.0708' to '2015.708'
  normalized_version,
removing '/home/chris/git/tzupdate/sdist/lib/python3.4/site-packages/maxminddb_geolite2-2015.708-py3.4.egg' (and everything under it)
creating /home/chris/git/tzupdate/sdist/lib/python3.4/site-packages/maxminddb_geolite2-2015.708-py3.4.egg
Extracting maxminddb_geolite2-2015.708-py3.4.egg to /home/chris/git/tzupdate/sdist/lib/python3.4/site-packages
maxminddb-geolite2 2015.708 is already the active version in easy-install.pth

Installed /home/chris/git/tzupdate/sdist/lib/python3.4/site-packages/maxminddb_geolite2-2015.708-py3.4.egg
error: The 'maxminddb' distribution was not found and is required by maxminddb-geolite2

SyntaxError on Docker Debian:buster-slim

Traceback (most recent call last):
  File "/usr/local/bin/tzupdate", line 6, in <module>
    from tzupdate import main
  File "/usr/local/lib/python2.7/dist-packages/tzupdate.py", line 69
    ) from None
         ^
SyntaxError: invalid syntax

How to reproduce:

  1. docker run --entrypoint /bin/sh -it debian:buster-slim
  2. apt -y update
  3. apt -y --no-install-recommends install locales curl lib32gcc1 ca-certificates python-pip
  4. pip install -U tzupdate
  5. tzupdate

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.